15f12c8d7Swinesync #ifdef __REACTOS__
25f12c8d7Swinesync #define NONAMELESSUNION
35f12c8d7Swinesync #define NONAMELESSSTRUCT
45f12c8d7Swinesync #include "precomp.h"
55f12c8d7Swinesync #else
6c2c66affSColin Finck /*
7c2c66affSColin Finck * Wininet - Url Cache functions
8c2c66affSColin Finck *
9c2c66affSColin Finck * Copyright 2001,2002 CodeWeavers
10c2c66affSColin Finck * Copyright 2003-2008 Robert Shearman
11c2c66affSColin Finck *
12c2c66affSColin Finck * Eric Kohl
13c2c66affSColin Finck * Aric Stewart
14c2c66affSColin Finck *
15c2c66affSColin Finck * This library is free software; you can redistribute it and/or
16c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
17c2c66affSColin Finck * License as published by the Free Software Foundation; either
18c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
19c2c66affSColin Finck *
20c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
21c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
22c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23c2c66affSColin Finck * Lesser General Public License for more details.
24c2c66affSColin Finck *
25c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
26c2c66affSColin Finck * License along with this library; if not, write to the Free Software
27c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28c2c66affSColin Finck */
29c2c66affSColin Finck
30bc01cef0SAmine Khaldi #define NONAMELESSUNION
31c239cdd4SAmine Khaldi #define NONAMELESSSTRUCT
32bc01cef0SAmine Khaldi
33bc01cef0SAmine Khaldi #include "ws2tcpip.h"
34bc01cef0SAmine Khaldi
35bc01cef0SAmine Khaldi #include <stdarg.h>
36bc01cef0SAmine Khaldi #include <stdio.h>
37bc01cef0SAmine Khaldi #include <stdlib.h>
38bc01cef0SAmine Khaldi #include <string.h>
39bc01cef0SAmine Khaldi #include <time.h>
40bc01cef0SAmine Khaldi
41bc01cef0SAmine Khaldi #include "windef.h"
42bc01cef0SAmine Khaldi #include "winbase.h"
43bc01cef0SAmine Khaldi #include "winuser.h"
44bc01cef0SAmine Khaldi #include "wininet.h"
45bc01cef0SAmine Khaldi #include "winineti.h"
46bc01cef0SAmine Khaldi #include "winerror.h"
47bc01cef0SAmine Khaldi #include "winreg.h"
48bc01cef0SAmine Khaldi #include "shlwapi.h"
49bc01cef0SAmine Khaldi #include "shlobj.h"
50bc01cef0SAmine Khaldi #include "shellapi.h"
51bc01cef0SAmine Khaldi
52c2c66affSColin Finck #include "internet.h"
53bc01cef0SAmine Khaldi #include "wine/debug.h"
545f12c8d7Swinesync #endif /* defined(__REACTOS__) */
55bc01cef0SAmine Khaldi
56bc01cef0SAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(wininet);
57c2c66affSColin Finck
58c2c66affSColin Finck static const char urlcache_ver_prefix[] = "WINE URLCache Ver ";
59c2c66affSColin Finck static const char urlcache_ver[] = "0.2012001";
60c2c66affSColin Finck
61c2c66affSColin Finck #ifndef CHAR_BIT
62c2c66affSColin Finck #define CHAR_BIT (8 * sizeof(CHAR))
63c2c66affSColin Finck #endif
64c2c66affSColin Finck
65c2c66affSColin Finck #define ENTRY_START_OFFSET 0x4000
66c2c66affSColin Finck #define DIR_LENGTH 8
67c2c66affSColin Finck #define MAX_DIR_NO 0x20
68c2c66affSColin Finck #define BLOCKSIZE 128
69c2c66affSColin Finck #define HASHTABLE_SIZE 448
70c2c66affSColin Finck #define HASHTABLE_NUM_ENTRIES 64 /* this needs to be power of 2, that divides HASHTABLE_SIZE */
71c2c66affSColin Finck #define HASHTABLE_BLOCKSIZE (HASHTABLE_SIZE / HASHTABLE_NUM_ENTRIES)
72c2c66affSColin Finck #define ALLOCATION_TABLE_OFFSET 0x250
73c2c66affSColin Finck #define ALLOCATION_TABLE_SIZE (ENTRY_START_OFFSET - ALLOCATION_TABLE_OFFSET)
74c2c66affSColin Finck #define MIN_BLOCK_NO 0x80
75c2c66affSColin Finck #define MAX_BLOCK_NO (ALLOCATION_TABLE_SIZE * CHAR_BIT)
76c2c66affSColin Finck #define FILE_SIZE(blocks) ((blocks) * BLOCKSIZE + ENTRY_START_OFFSET)
77c2c66affSColin Finck
78c2c66affSColin Finck #define HASHTABLE_URL 0
79c2c66affSColin Finck #define HASHTABLE_DEL 1
80c2c66affSColin Finck #define HASHTABLE_LOCK 2
81c2c66affSColin Finck #define HASHTABLE_FREE 3
82c2c66affSColin Finck #define HASHTABLE_REDR 5
83c2c66affSColin Finck #define HASHTABLE_FLAG_BITS 6
84c2c66affSColin Finck
85c2c66affSColin Finck #define PENDING_DELETE_CACHE_ENTRY 0x00400000
86c2c66affSColin Finck #define INSTALLED_CACHE_ENTRY 0x10000000
87c2c66affSColin Finck #define GET_INSTALLED_ENTRY 0x200
88c2c66affSColin Finck #define CACHE_CONTAINER_NO_SUBDIR 0xFE
89c2c66affSColin Finck
90c2c66affSColin Finck #define CACHE_HEADER_DATA_ROOT_LEAK_OFFSET 0x16
91c2c66affSColin Finck
92c2c66affSColin Finck #define FILETIME_SECOND 10000000
93c2c66affSColin Finck
94c2c66affSColin Finck #define DWORD_SIG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
95c2c66affSColin Finck #define URL_SIGNATURE DWORD_SIG('U','R','L',' ')
96c2c66affSColin Finck #define REDR_SIGNATURE DWORD_SIG('R','E','D','R')
97c2c66affSColin Finck #define LEAK_SIGNATURE DWORD_SIG('L','E','A','K')
98c2c66affSColin Finck #define HASH_SIGNATURE DWORD_SIG('H','A','S','H')
99c2c66affSColin Finck
100c2c66affSColin Finck #define DWORD_ALIGN(x) ( (DWORD)(((DWORD)(x)+sizeof(DWORD)-1)/sizeof(DWORD))*sizeof(DWORD) )
101c2c66affSColin Finck
102c2c66affSColin Finck #define URLCACHE_FIND_ENTRY_HANDLE_MAGIC 0xF389ABCD
103c2c66affSColin Finck
104c2c66affSColin Finck typedef struct
105c2c66affSColin Finck {
106c2c66affSColin Finck DWORD signature;
107c2c66affSColin Finck DWORD blocks_used; /* number of 128byte blocks used by this entry */
108c2c66affSColin Finck } entry_header;
109c2c66affSColin Finck
110c2c66affSColin Finck typedef struct
111c2c66affSColin Finck {
112c2c66affSColin Finck entry_header header;
113c2c66affSColin Finck FILETIME modification_time;
114c2c66affSColin Finck FILETIME access_time;
115c2c66affSColin Finck WORD expire_date; /* expire date in dos format */
116c2c66affSColin Finck WORD expire_time; /* expire time in dos format */
117c2c66affSColin Finck DWORD unk1; /* usually zero */
118c2c66affSColin Finck ULARGE_INTEGER size; /* see INTERNET_CACHE_ENTRY_INFO::dwSizeLow/High */
119c2c66affSColin Finck DWORD unk2; /* usually zero */
120c2c66affSColin Finck DWORD exempt_delta; /* see INTERNET_CACHE_ENTRY_INFO::dwExemptDelta */
121c2c66affSColin Finck DWORD unk3; /* usually 0x60 */
122c2c66affSColin Finck DWORD url_off; /* offset of start of url from start of entry */
123c2c66affSColin Finck BYTE cache_dir; /* index of cache directory this url is stored in */
124c2c66affSColin Finck BYTE unk4; /* usually zero */
125c2c66affSColin Finck WORD unk5; /* usually 0x1010 */
126c2c66affSColin Finck DWORD local_name_off; /* offset of start of local filename from start of entry */
127c2c66affSColin Finck DWORD cache_entry_type; /* see INTERNET_CACHE_ENTRY_INFO::CacheEntryType */
128c2c66affSColin Finck DWORD header_info_off; /* offset of start of header info from start of entry */
129c2c66affSColin Finck DWORD header_info_size;
130c2c66affSColin Finck DWORD file_extension_off; /* offset of start of file extension from start of entry */
131c2c66affSColin Finck WORD sync_date; /* last sync date in dos format */
132c2c66affSColin Finck WORD sync_time; /* last sync time in dos format */
133c2c66affSColin Finck DWORD hit_rate; /* see INTERNET_CACHE_ENTRY_INFO::dwHitRate */
134c2c66affSColin Finck DWORD use_count; /* see INTERNET_CACHE_ENTRY_INFO::dwUseCount */
135c2c66affSColin Finck WORD write_date;
136c2c66affSColin Finck WORD write_time;
137c2c66affSColin Finck DWORD unk7; /* usually zero */
138c2c66affSColin Finck DWORD unk8; /* usually zero */
139c2c66affSColin Finck /* packing to dword align start of next field */
140c2c66affSColin Finck /* CHAR szSourceUrlName[]; (url) */
141c2c66affSColin Finck /* packing to dword align start of next field */
142c2c66affSColin Finck /* CHAR szLocalFileName[]; (local file name excluding path) */
143c2c66affSColin Finck /* packing to dword align start of next field */
144c2c66affSColin Finck /* CHAR szHeaderInfo[]; (header info) */
145c2c66affSColin Finck } entry_url;
146c2c66affSColin Finck
147c2c66affSColin Finck struct hash_entry
148c2c66affSColin Finck {
149c2c66affSColin Finck DWORD key;
150c2c66affSColin Finck DWORD offset;
151c2c66affSColin Finck };
152c2c66affSColin Finck
153c2c66affSColin Finck typedef struct
154c2c66affSColin Finck {
155c2c66affSColin Finck entry_header header;
156c2c66affSColin Finck DWORD next;
157c2c66affSColin Finck DWORD id;
158c2c66affSColin Finck struct hash_entry hash_table[HASHTABLE_SIZE];
159c2c66affSColin Finck } entry_hash_table;
160c2c66affSColin Finck
161c2c66affSColin Finck typedef struct
162c2c66affSColin Finck {
163c2c66affSColin Finck char signature[28];
164c2c66affSColin Finck DWORD size;
165c2c66affSColin Finck DWORD hash_table_off;
166c2c66affSColin Finck DWORD capacity_in_blocks;
167c2c66affSColin Finck DWORD blocks_in_use;
168c2c66affSColin Finck DWORD unk1;
169c2c66affSColin Finck ULARGE_INTEGER cache_limit;
170c2c66affSColin Finck ULARGE_INTEGER cache_usage;
171c2c66affSColin Finck ULARGE_INTEGER exempt_usage;
172c2c66affSColin Finck DWORD dirs_no;
173c2c66affSColin Finck struct _directory_data
174c2c66affSColin Finck {
175c2c66affSColin Finck DWORD files_no;
176c2c66affSColin Finck char name[DIR_LENGTH];
177c2c66affSColin Finck } directory_data[MAX_DIR_NO];
178c2c66affSColin Finck DWORD options[0x21];
179c2c66affSColin Finck BYTE allocation_table[ALLOCATION_TABLE_SIZE];
180c2c66affSColin Finck } urlcache_header;
181c2c66affSColin Finck
182c2c66affSColin Finck typedef struct
183c2c66affSColin Finck {
184c2c66affSColin Finck HANDLE file;
185c2c66affSColin Finck CHAR url[1];
186c2c66affSColin Finck } stream_handle;
187c2c66affSColin Finck
188c2c66affSColin Finck typedef struct
189c2c66affSColin Finck {
190c2c66affSColin Finck struct list entry; /* part of a list */
191c2c66affSColin Finck char *cache_prefix; /* string that has to be prefixed for this container to be used */
192c2c66affSColin Finck LPWSTR path; /* path to url container directory */
193c2c66affSColin Finck HANDLE mapping; /* handle of file mapping */
194c2c66affSColin Finck DWORD file_size; /* size of file when mapping was opened */
195c2c66affSColin Finck HANDLE mutex; /* handle of mutex */
196c2c66affSColin Finck DWORD default_entry_type;
197c2c66affSColin Finck } cache_container;
198c2c66affSColin Finck
199c2c66affSColin Finck typedef struct
200c2c66affSColin Finck {
201c2c66affSColin Finck DWORD magic;
202c2c66affSColin Finck char *url_search_pattern;
203c2c66affSColin Finck DWORD container_idx;
204c2c66affSColin Finck DWORD hash_table_idx;
205c2c66affSColin Finck DWORD hash_entry_idx;
206c2c66affSColin Finck } find_handle;
207c2c66affSColin Finck
208c2c66affSColin Finck /* List of all containers available */
209c2c66affSColin Finck static struct list UrlContainers = LIST_INIT(UrlContainers);
210c2c66affSColin Finck /* ReactOS r54992 */
211c2c66affSColin Finck BOOL bDefaultContainersAdded = FALSE;
212c2c66affSColin Finck
heap_strdupWtoUTF8(LPCWSTR str)213c2c66affSColin Finck static inline char *heap_strdupWtoUTF8(LPCWSTR str)
214c2c66affSColin Finck {
215c2c66affSColin Finck char *ret = NULL;
216c2c66affSColin Finck
217c2c66affSColin Finck if(str) {
218c2c66affSColin Finck DWORD size = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
219c2c66affSColin Finck ret = heap_alloc(size);
220c2c66affSColin Finck if(ret)
221c2c66affSColin Finck WideCharToMultiByte(CP_UTF8, 0, str, -1, ret, size, NULL, NULL);
222c2c66affSColin Finck }
223c2c66affSColin Finck
224c2c66affSColin Finck return ret;
225c2c66affSColin Finck }
226c2c66affSColin Finck
227c2c66affSColin Finck /***********************************************************************
228c2c66affSColin Finck * urlcache_block_is_free (Internal)
229c2c66affSColin Finck *
230c2c66affSColin Finck * Is the specified block number free?
231c2c66affSColin Finck *
232c2c66affSColin Finck * RETURNS
233c2c66affSColin Finck * zero if free
234c2c66affSColin Finck * non-zero otherwise
235c2c66affSColin Finck *
236c2c66affSColin Finck */
urlcache_block_is_free(BYTE * allocation_table,DWORD block_number)237c2c66affSColin Finck static inline BYTE urlcache_block_is_free(BYTE *allocation_table, DWORD block_number)
238c2c66affSColin Finck {
239c2c66affSColin Finck BYTE mask = 1 << (block_number%CHAR_BIT);
240c2c66affSColin Finck return (allocation_table[block_number/CHAR_BIT] & mask) == 0;
241c2c66affSColin Finck }
242c2c66affSColin Finck
243c2c66affSColin Finck /***********************************************************************
244c2c66affSColin Finck * urlcache_block_free (Internal)
245c2c66affSColin Finck *
246c2c66affSColin Finck * Marks the specified block as free
247c2c66affSColin Finck *
248c2c66affSColin Finck * CAUTION
249c2c66affSColin Finck * this function is not updating used blocks count
250c2c66affSColin Finck *
251c2c66affSColin Finck * RETURNS
252c2c66affSColin Finck * nothing
253c2c66affSColin Finck *
254c2c66affSColin Finck */
urlcache_block_free(BYTE * allocation_table,DWORD block_number)255c2c66affSColin Finck static inline void urlcache_block_free(BYTE *allocation_table, DWORD block_number)
256c2c66affSColin Finck {
257c2c66affSColin Finck BYTE mask = ~(1 << (block_number%CHAR_BIT));
258c2c66affSColin Finck allocation_table[block_number/CHAR_BIT] &= mask;
259c2c66affSColin Finck }
260c2c66affSColin Finck
261c2c66affSColin Finck /***********************************************************************
262c2c66affSColin Finck * urlcache_block_alloc (Internal)
263c2c66affSColin Finck *
264c2c66affSColin Finck * Marks the specified block as allocated
265c2c66affSColin Finck *
266c2c66affSColin Finck * CAUTION
267c2c66affSColin Finck * this function is not updating used blocks count
268c2c66affSColin Finck *
269c2c66affSColin Finck * RETURNS
270c2c66affSColin Finck * nothing
271c2c66affSColin Finck *
272c2c66affSColin Finck */
urlcache_block_alloc(BYTE * allocation_table,DWORD block_number)273c2c66affSColin Finck static inline void urlcache_block_alloc(BYTE *allocation_table, DWORD block_number)
274c2c66affSColin Finck {
275c2c66affSColin Finck BYTE mask = 1 << (block_number%CHAR_BIT);
276c2c66affSColin Finck allocation_table[block_number/CHAR_BIT] |= mask;
277c2c66affSColin Finck }
278c2c66affSColin Finck
279c2c66affSColin Finck /***********************************************************************
280c2c66affSColin Finck * urlcache_entry_alloc (Internal)
281c2c66affSColin Finck *
282c2c66affSColin Finck * Finds and allocates the first block of free space big enough and
283c2c66affSColin Finck * sets entry to point to it.
284c2c66affSColin Finck *
285c2c66affSColin Finck * RETURNS
286c2c66affSColin Finck * ERROR_SUCCESS when free memory block was found
287c2c66affSColin Finck * Any other Win32 error code if the entry could not be added
288c2c66affSColin Finck *
289c2c66affSColin Finck */
urlcache_entry_alloc(urlcache_header * header,DWORD blocks_needed,entry_header ** entry)290c2c66affSColin Finck static DWORD urlcache_entry_alloc(urlcache_header *header, DWORD blocks_needed, entry_header **entry)
291c2c66affSColin Finck {
292c2c66affSColin Finck DWORD block, block_size;
293c2c66affSColin Finck
294c2c66affSColin Finck for(block=0; block<header->capacity_in_blocks; block+=block_size+1)
295c2c66affSColin Finck {
296c2c66affSColin Finck block_size = 0;
297c2c66affSColin Finck while(block_size<blocks_needed && block_size+block<header->capacity_in_blocks
298c2c66affSColin Finck && urlcache_block_is_free(header->allocation_table, block+block_size))
299c2c66affSColin Finck block_size++;
300c2c66affSColin Finck
301c2c66affSColin Finck if(block_size == blocks_needed)
302c2c66affSColin Finck {
303c2c66affSColin Finck DWORD index;
304c2c66affSColin Finck
305c2c66affSColin Finck TRACE("Found free blocks starting at no. %d (0x%x)\n", block, ENTRY_START_OFFSET+block*BLOCKSIZE);
306c2c66affSColin Finck
307c2c66affSColin Finck for(index=0; index<blocks_needed; index++)
308c2c66affSColin Finck urlcache_block_alloc(header->allocation_table, block+index);
309c2c66affSColin Finck
310c2c66affSColin Finck *entry = (entry_header*)((BYTE*)header+ENTRY_START_OFFSET+block*BLOCKSIZE);
311c2c66affSColin Finck for(index=0; index<blocks_needed*BLOCKSIZE/sizeof(DWORD); index++)
312c2c66affSColin Finck ((DWORD*)*entry)[index] = 0xdeadbeef;
313c2c66affSColin Finck (*entry)->blocks_used = blocks_needed;
314c2c66affSColin Finck
315c2c66affSColin Finck header->blocks_in_use += blocks_needed;
316c2c66affSColin Finck return ERROR_SUCCESS;
317c2c66affSColin Finck }
318c2c66affSColin Finck }
319c2c66affSColin Finck
320c2c66affSColin Finck return ERROR_HANDLE_DISK_FULL;
321c2c66affSColin Finck }
322c2c66affSColin Finck
323c2c66affSColin Finck /***********************************************************************
324c2c66affSColin Finck * urlcache_entry_free (Internal)
325c2c66affSColin Finck *
326c2c66affSColin Finck * Deletes the specified entry and frees the space allocated to it
327c2c66affSColin Finck *
328c2c66affSColin Finck * RETURNS
329c2c66affSColin Finck * TRUE if it succeeded
330c2c66affSColin Finck * FALSE if it failed
331c2c66affSColin Finck *
332c2c66affSColin Finck */
urlcache_entry_free(urlcache_header * header,entry_header * entry)333c2c66affSColin Finck static BOOL urlcache_entry_free(urlcache_header *header, entry_header *entry)
334c2c66affSColin Finck {
335c2c66affSColin Finck DWORD start_block, block;
336c2c66affSColin Finck
337c2c66affSColin Finck /* update allocation table */
338c2c66affSColin Finck start_block = ((DWORD)((BYTE*)entry - (BYTE*)header) - ENTRY_START_OFFSET) / BLOCKSIZE;
339c2c66affSColin Finck for(block = start_block; block < start_block+entry->blocks_used; block++)
340c2c66affSColin Finck urlcache_block_free(header->allocation_table, block);
341c2c66affSColin Finck
342c2c66affSColin Finck header->blocks_in_use -= entry->blocks_used;
343c2c66affSColin Finck return TRUE;
344c2c66affSColin Finck }
345c2c66affSColin Finck
346c2c66affSColin Finck /***********************************************************************
347c2c66affSColin Finck * urlcache_create_hash_table (Internal)
348c2c66affSColin Finck *
349c2c66affSColin Finck * Creates a new hash table in free space and adds it to the chain of existing
350c2c66affSColin Finck * hash tables.
351c2c66affSColin Finck *
352c2c66affSColin Finck * RETURNS
353c2c66affSColin Finck * ERROR_SUCCESS if the hash table was created
354c2c66affSColin Finck * ERROR_DISK_FULL if the hash table could not be created
355c2c66affSColin Finck *
356c2c66affSColin Finck */
urlcache_create_hash_table(urlcache_header * header,entry_hash_table * hash_table_prev,entry_hash_table ** hash_table)357c2c66affSColin Finck static DWORD urlcache_create_hash_table(urlcache_header *header, entry_hash_table *hash_table_prev, entry_hash_table **hash_table)
358c2c66affSColin Finck {
359c2c66affSColin Finck DWORD dwOffset, error;
360c2c66affSColin Finck int i;
361c2c66affSColin Finck
362c2c66affSColin Finck if((error = urlcache_entry_alloc(header, 0x20, (entry_header**)hash_table)) != ERROR_SUCCESS)
363c2c66affSColin Finck return error;
364c2c66affSColin Finck
365c2c66affSColin Finck dwOffset = (BYTE*)*hash_table-(BYTE*)header;
366c2c66affSColin Finck
367c2c66affSColin Finck if(hash_table_prev)
368c2c66affSColin Finck hash_table_prev->next = dwOffset;
369c2c66affSColin Finck else
370c2c66affSColin Finck header->hash_table_off = dwOffset;
371c2c66affSColin Finck
372c2c66affSColin Finck (*hash_table)->header.signature = HASH_SIGNATURE;
373c2c66affSColin Finck (*hash_table)->next = 0;
374c2c66affSColin Finck (*hash_table)->id = hash_table_prev ? hash_table_prev->id+1 : 0;
375c2c66affSColin Finck for(i = 0; i < HASHTABLE_SIZE; i++) {
376c2c66affSColin Finck (*hash_table)->hash_table[i].offset = HASHTABLE_FREE;
377c2c66affSColin Finck (*hash_table)->hash_table[i].key = HASHTABLE_FREE;
378c2c66affSColin Finck }
379c2c66affSColin Finck return ERROR_SUCCESS;
380c2c66affSColin Finck }
381c2c66affSColin Finck
382c2c66affSColin Finck /***********************************************************************
383c2c66affSColin Finck * cache_container_create_object_name (Internal)
384c2c66affSColin Finck *
385c2c66affSColin Finck * Converts a path to a name suitable for use as a Win32 object name.
386c2c66affSColin Finck * Replaces '\\' characters in-place with the specified character
387c2c66affSColin Finck * (usually '_' or '!')
388c2c66affSColin Finck *
389c2c66affSColin Finck * RETURNS
390c2c66affSColin Finck * nothing
391c2c66affSColin Finck *
392c2c66affSColin Finck */
cache_container_create_object_name(LPWSTR lpszPath,WCHAR replace)393c2c66affSColin Finck static void cache_container_create_object_name(LPWSTR lpszPath, WCHAR replace)
394c2c66affSColin Finck {
395c2c66affSColin Finck for (; *lpszPath; lpszPath++)
396c2c66affSColin Finck {
397c2c66affSColin Finck if (*lpszPath == '\\')
398c2c66affSColin Finck *lpszPath = replace;
399c2c66affSColin Finck }
400c2c66affSColin Finck }
401c2c66affSColin Finck
402c2c66affSColin Finck /* Caller must hold container lock */
cache_container_map_index(HANDLE file,const WCHAR * path,DWORD size,BOOL * validate)403c2c66affSColin Finck static HANDLE cache_container_map_index(HANDLE file, const WCHAR *path, DWORD size, BOOL *validate)
404c2c66affSColin Finck {
405c2c66affSColin Finck WCHAR mapping_name[MAX_PATH];
406c2c66affSColin Finck HANDLE mapping;
407c2c66affSColin Finck
408*e152f78aSwinesync wsprintfW(mapping_name, L"%sindex.dat_%lu", path, size);
409c2c66affSColin Finck cache_container_create_object_name(mapping_name, '_');
410c2c66affSColin Finck
411c2c66affSColin Finck mapping = OpenFileMappingW(FILE_MAP_WRITE, FALSE, mapping_name);
412c2c66affSColin Finck if(mapping) {
413c2c66affSColin Finck if(validate) *validate = FALSE;
414c2c66affSColin Finck return mapping;
415c2c66affSColin Finck }
416c2c66affSColin Finck
417c2c66affSColin Finck if(validate) *validate = TRUE;
418c2c66affSColin Finck return CreateFileMappingW(file, NULL, PAGE_READWRITE, 0, 0, mapping_name);
419c2c66affSColin Finck }
420c2c66affSColin Finck
421c2c66affSColin Finck /* Caller must hold container lock */
cache_container_set_size(cache_container * container,HANDLE file,DWORD blocks_no)422c2c66affSColin Finck static DWORD cache_container_set_size(cache_container *container, HANDLE file, DWORD blocks_no)
423c2c66affSColin Finck {
424c2c66affSColin Finck DWORD file_size = FILE_SIZE(blocks_no);
425c2c66affSColin Finck WCHAR dir_path[MAX_PATH], *dir_name;
426c2c66affSColin Finck entry_hash_table *hashtable_entry;
427c2c66affSColin Finck urlcache_header *header;
428c2c66affSColin Finck HANDLE mapping;
429c2c66affSColin Finck FILETIME ft;
430c2c66affSColin Finck HKEY key;
431c2c66affSColin Finck int i, j;
432c2c66affSColin Finck
433c2c66affSColin Finck if(SetFilePointer(file, file_size, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
434c2c66affSColin Finck return GetLastError();
435c2c66affSColin Finck
436c2c66affSColin Finck if(!SetEndOfFile(file))
437c2c66affSColin Finck return GetLastError();
438c2c66affSColin Finck
439c2c66affSColin Finck mapping = cache_container_map_index(file, container->path, file_size, NULL);
440c2c66affSColin Finck if(!mapping)
441c2c66affSColin Finck return GetLastError();
442c2c66affSColin Finck
443c2c66affSColin Finck header = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
444c2c66affSColin Finck if(!header) {
445c2c66affSColin Finck CloseHandle(mapping);
446c2c66affSColin Finck return GetLastError();
447c2c66affSColin Finck }
448c2c66affSColin Finck
449c2c66affSColin Finck if(blocks_no != MIN_BLOCK_NO) {
450c2c66affSColin Finck if(file_size > header->size)
451c2c66affSColin Finck memset((char*)header+header->size, 0, file_size-header->size);
452c2c66affSColin Finck header->size = file_size;
453c2c66affSColin Finck header->capacity_in_blocks = blocks_no;
454c2c66affSColin Finck
455c2c66affSColin Finck UnmapViewOfFile(header);
456c2c66affSColin Finck CloseHandle(container->mapping);
457c2c66affSColin Finck container->mapping = mapping;
458c2c66affSColin Finck container->file_size = file_size;
459c2c66affSColin Finck return ERROR_SUCCESS;
460c2c66affSColin Finck }
461c2c66affSColin Finck
462c2c66affSColin Finck memset(header, 0, file_size);
463c2c66affSColin Finck /* First set some constants and defaults in the header */
464c2c66affSColin Finck memcpy(header->signature, urlcache_ver_prefix, sizeof(urlcache_ver_prefix)-1);
465c2c66affSColin Finck memcpy(header->signature+sizeof(urlcache_ver_prefix)-1, urlcache_ver, sizeof(urlcache_ver)-1);
466c2c66affSColin Finck header->size = file_size;
467c2c66affSColin Finck header->capacity_in_blocks = blocks_no;
468c2c66affSColin Finck /* 127MB - taken from default for Windows 2000 */
469c2c66affSColin Finck header->cache_limit.QuadPart = 0x07ff5400;
470c2c66affSColin Finck /* Copied from a Windows 2000 cache index */
471c2c66affSColin Finck header->dirs_no = container->default_entry_type==NORMAL_CACHE_ENTRY ? 4 : 0;
472c2c66affSColin Finck
473c2c66affSColin Finck /* If the registry has a cache size set, use the registry value */
474*e152f78aSwinesync if(RegOpenKeyW(HKEY_CURRENT_USER,
475*e152f78aSwinesync L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Cache\\Content", &key) == ERROR_SUCCESS) {
476c2c66affSColin Finck DWORD dw, len = sizeof(dw), keytype;
477c2c66affSColin Finck
478*e152f78aSwinesync if(RegQueryValueExW(key, L"CacheLimit", NULL, &keytype, (BYTE*)&dw, &len) == ERROR_SUCCESS &&
479c2c66affSColin Finck keytype == REG_DWORD)
480c2c66affSColin Finck header->cache_limit.QuadPart = (ULONGLONG)dw * 1024;
481c2c66affSColin Finck RegCloseKey(key);
482c2c66affSColin Finck }
483c2c66affSColin Finck
484c2c66affSColin Finck urlcache_create_hash_table(header, NULL, &hashtable_entry);
485c2c66affSColin Finck
486c2c66affSColin Finck /* Last step - create the directories */
4875f12c8d7Swinesync lstrcpyW(dir_path, container->path);
4885f12c8d7Swinesync dir_name = dir_path + lstrlenW(dir_path);
489c2c66affSColin Finck dir_name[8] = 0;
490c2c66affSColin Finck
491c2c66affSColin Finck GetSystemTimeAsFileTime(&ft);
492c2c66affSColin Finck
493c2c66affSColin Finck for(i=0; i<header->dirs_no; ++i) {
494c2c66affSColin Finck header->directory_data[i].files_no = 0;
495c2c66affSColin Finck for(j=0;; ++j) {
496c2c66affSColin Finck ULONGLONG n = ft.dwHighDateTime;
497c2c66affSColin Finck int k;
498c2c66affSColin Finck
499c2c66affSColin Finck /* Generate a file name to attempt to create.
500c2c66affSColin Finck * This algorithm will create what will appear
501c2c66affSColin Finck * to be random and unrelated directory names
502c2c66affSColin Finck * of up to 9 characters in length.
503c2c66affSColin Finck */
504c2c66affSColin Finck n <<= 32;
505c2c66affSColin Finck n += ft.dwLowDateTime;
506c2c66affSColin Finck n ^= ((ULONGLONG) i << 56) | ((ULONGLONG) j << 48);
507c2c66affSColin Finck
508c2c66affSColin Finck for(k = 0; k < 8; ++k) {
509c2c66affSColin Finck int r = (n % 36);
510c2c66affSColin Finck
511c2c66affSColin Finck /* Dividing by a prime greater than 36 helps
512c2c66affSColin Finck * with the appearance of randomness
513c2c66affSColin Finck */
514c2c66affSColin Finck n /= 37;
515c2c66affSColin Finck
516c2c66affSColin Finck if(r < 10)
517c2c66affSColin Finck dir_name[k] = '0' + r;
518c2c66affSColin Finck else
519c2c66affSColin Finck dir_name[k] = 'A' + (r - 10);
520c2c66affSColin Finck }
521c2c66affSColin Finck
522c2c66affSColin Finck if(CreateDirectoryW(dir_path, 0)) {
523c2c66affSColin Finck /* The following is OK because we generated an
524c2c66affSColin Finck * 8 character directory name made from characters
525c2c66affSColin Finck * [A-Z0-9], which are equivalent for all code
526c2c66affSColin Finck * pages and for UTF-16
527c2c66affSColin Finck */
528c2c66affSColin Finck for (k = 0; k < 8; ++k)
529c2c66affSColin Finck header->directory_data[i].name[k] = dir_name[k];
530c2c66affSColin Finck break;
531c2c66affSColin Finck }else if(j >= 255) {
532c2c66affSColin Finck /* Give up. The most likely cause of this
533c2c66affSColin Finck * is a full disk, but whatever the cause
534c2c66affSColin Finck * is, it should be more than apparent that
535c2c66affSColin Finck * we won't succeed.
536c2c66affSColin Finck */
537c2c66affSColin Finck UnmapViewOfFile(header);
538c2c66affSColin Finck CloseHandle(mapping);
539c2c66affSColin Finck return GetLastError();
540c2c66affSColin Finck }
541c2c66affSColin Finck }
542c2c66affSColin Finck }
543c2c66affSColin Finck
544c2c66affSColin Finck UnmapViewOfFile(header);
545c2c66affSColin Finck CloseHandle(container->mapping);
546c2c66affSColin Finck container->mapping = mapping;
547c2c66affSColin Finck container->file_size = file_size;
548c2c66affSColin Finck return ERROR_SUCCESS;
549c2c66affSColin Finck }
550c2c66affSColin Finck
cache_container_is_valid(urlcache_header * header,DWORD file_size)551c2c66affSColin Finck static BOOL cache_container_is_valid(urlcache_header *header, DWORD file_size)
552c2c66affSColin Finck {
553c2c66affSColin Finck DWORD allocation_size, count_bits, i;
554c2c66affSColin Finck
555c2c66affSColin Finck if(file_size < FILE_SIZE(MIN_BLOCK_NO))
556c2c66affSColin Finck return FALSE;
557c2c66affSColin Finck
558c2c66affSColin Finck if(file_size != header->size)
559c2c66affSColin Finck return FALSE;
560c2c66affSColin Finck
561c2c66affSColin Finck if (!memcmp(header->signature, urlcache_ver_prefix, sizeof(urlcache_ver_prefix)-1) &&
562c2c66affSColin Finck memcmp(header->signature+sizeof(urlcache_ver_prefix)-1, urlcache_ver, sizeof(urlcache_ver)-1))
563c2c66affSColin Finck return FALSE;
564c2c66affSColin Finck
565c2c66affSColin Finck if(FILE_SIZE(header->capacity_in_blocks) != file_size)
566c2c66affSColin Finck return FALSE;
567c2c66affSColin Finck
568c2c66affSColin Finck allocation_size = 0;
569c2c66affSColin Finck for(i=0; i<header->capacity_in_blocks/8; i++) {
570c2c66affSColin Finck for(count_bits = header->allocation_table[i]; count_bits!=0; count_bits>>=1) {
571c2c66affSColin Finck if(count_bits & 1)
572c2c66affSColin Finck allocation_size++;
573c2c66affSColin Finck }
574c2c66affSColin Finck }
575c2c66affSColin Finck if(allocation_size != header->blocks_in_use)
576c2c66affSColin Finck return FALSE;
577c2c66affSColin Finck
578c2c66affSColin Finck for(; i<ALLOCATION_TABLE_SIZE; i++) {
579c2c66affSColin Finck if(header->allocation_table[i])
580c2c66affSColin Finck return FALSE;
581c2c66affSColin Finck }
582c2c66affSColin Finck
583c2c66affSColin Finck return TRUE;
584c2c66affSColin Finck }
585c2c66affSColin Finck
586c2c66affSColin Finck /***********************************************************************
587c2c66affSColin Finck * cache_container_open_index (Internal)
588c2c66affSColin Finck *
589c2c66affSColin Finck * Opens the index file and saves mapping handle
590c2c66affSColin Finck *
591c2c66affSColin Finck * RETURNS
592c2c66affSColin Finck * ERROR_SUCCESS if succeeded
593c2c66affSColin Finck * Any other Win32 error code if failed
594c2c66affSColin Finck *
595c2c66affSColin Finck */
cache_container_open_index(cache_container * container,DWORD blocks_no)596c2c66affSColin Finck static DWORD cache_container_open_index(cache_container *container, DWORD blocks_no)
597c2c66affSColin Finck {
598c2c66affSColin Finck HANDLE file;
599c2c66affSColin Finck WCHAR index_path[MAX_PATH];
600c2c66affSColin Finck DWORD file_size;
601c2c66affSColin Finck BOOL validate;
602c2c66affSColin Finck
603c2c66affSColin Finck WaitForSingleObject(container->mutex, INFINITE);
604c2c66affSColin Finck
605c2c66affSColin Finck if(container->mapping) {
606c2c66affSColin Finck ReleaseMutex(container->mutex);
607c2c66affSColin Finck return ERROR_SUCCESS;
608c2c66affSColin Finck }
609c2c66affSColin Finck
6105f12c8d7Swinesync lstrcpyW(index_path, container->path);
611*e152f78aSwinesync lstrcatW(index_path, L"index.dat");
612c2c66affSColin Finck
613c2c66affSColin Finck file = CreateFileW(index_path, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
614c2c66affSColin Finck if(file == INVALID_HANDLE_VALUE) {
615c2c66affSColin Finck /* Maybe the directory wasn't there? Try to create it */
616c2c66affSColin Finck if(CreateDirectoryW(container->path, 0))
617c2c66affSColin Finck file = CreateFileW(index_path, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
618c2c66affSColin Finck }
619c2c66affSColin Finck if(file == INVALID_HANDLE_VALUE) {
620c2c66affSColin Finck TRACE("Could not open or create cache index file \"%s\"\n", debugstr_w(index_path));
621c2c66affSColin Finck ReleaseMutex(container->mutex);
622c2c66affSColin Finck return GetLastError();
623c2c66affSColin Finck }
624c2c66affSColin Finck
625c2c66affSColin Finck file_size = GetFileSize(file, NULL);
626c2c66affSColin Finck if(file_size == INVALID_FILE_SIZE) {
627c2c66affSColin Finck CloseHandle(file);
628c2c66affSColin Finck ReleaseMutex(container->mutex);
629c2c66affSColin Finck return GetLastError();
630c2c66affSColin Finck }
631c2c66affSColin Finck
632c2c66affSColin Finck if(blocks_no < MIN_BLOCK_NO)
633c2c66affSColin Finck blocks_no = MIN_BLOCK_NO;
634c2c66affSColin Finck else if(blocks_no > MAX_BLOCK_NO)
635c2c66affSColin Finck blocks_no = MAX_BLOCK_NO;
636c2c66affSColin Finck
637c2c66affSColin Finck if(file_size < FILE_SIZE(blocks_no)) {
638c2c66affSColin Finck DWORD ret = cache_container_set_size(container, file, blocks_no);
639c2c66affSColin Finck CloseHandle(file);
640c2c66affSColin Finck ReleaseMutex(container->mutex);
641c2c66affSColin Finck return ret;
642c2c66affSColin Finck }
643c2c66affSColin Finck
644c2c66affSColin Finck container->file_size = file_size;
645c2c66affSColin Finck container->mapping = cache_container_map_index(file, container->path, file_size, &validate);
646c2c66affSColin Finck CloseHandle(file);
647c2c66affSColin Finck if(container->mapping && validate) {
648c2c66affSColin Finck urlcache_header *header = MapViewOfFile(container->mapping, FILE_MAP_WRITE, 0, 0, 0);
649c2c66affSColin Finck
650c2c66affSColin Finck if(header && !cache_container_is_valid(header, file_size)) {
651c2c66affSColin Finck WARN("detected old or broken index.dat file\n");
652c2c66affSColin Finck UnmapViewOfFile(header);
653c2c66affSColin Finck FreeUrlCacheSpaceW(container->path, 100, 0);
654c2c66affSColin Finck }else if(header) {
655c2c66affSColin Finck UnmapViewOfFile(header);
656c2c66affSColin Finck }else {
657c2c66affSColin Finck CloseHandle(container->mapping);
658c2c66affSColin Finck container->mapping = NULL;
659c2c66affSColin Finck }
660c2c66affSColin Finck }
661c2c66affSColin Finck
662c2c66affSColin Finck if(!container->mapping)
663c2c66affSColin Finck {
664c2c66affSColin Finck ERR("Couldn't create file mapping (error is %d)\n", GetLastError());
665c2c66affSColin Finck ReleaseMutex(container->mutex);
666c2c66affSColin Finck return GetLastError();
667c2c66affSColin Finck }
668c2c66affSColin Finck
669c2c66affSColin Finck ReleaseMutex(container->mutex);
670c2c66affSColin Finck return ERROR_SUCCESS;
671c2c66affSColin Finck }
672c2c66affSColin Finck
673c2c66affSColin Finck /***********************************************************************
674c2c66affSColin Finck * cache_container_close_index (Internal)
675c2c66affSColin Finck *
676c2c66affSColin Finck * Closes the index
677c2c66affSColin Finck *
678c2c66affSColin Finck * RETURNS
679c2c66affSColin Finck * nothing
680c2c66affSColin Finck *
681c2c66affSColin Finck */
cache_container_close_index(cache_container * pContainer)682c2c66affSColin Finck static void cache_container_close_index(cache_container *pContainer)
683c2c66affSColin Finck {
684c2c66affSColin Finck CloseHandle(pContainer->mapping);
685c2c66affSColin Finck pContainer->mapping = NULL;
686c2c66affSColin Finck }
687c2c66affSColin Finck
cache_containers_add(const char * cache_prefix,LPCWSTR path,DWORD default_entry_type,LPWSTR mutex_name)688c2c66affSColin Finck static BOOL cache_containers_add(const char *cache_prefix, LPCWSTR path,
689c2c66affSColin Finck DWORD default_entry_type, LPWSTR mutex_name)
690c2c66affSColin Finck {
691c2c66affSColin Finck cache_container *pContainer = heap_alloc(sizeof(cache_container));
692c2c66affSColin Finck int cache_prefix_len = strlen(cache_prefix);
693c2c66affSColin Finck
694c2c66affSColin Finck if (!pContainer)
695c2c66affSColin Finck {
696c2c66affSColin Finck return FALSE;
697c2c66affSColin Finck }
698c2c66affSColin Finck
699c2c66affSColin Finck pContainer->mapping = NULL;
700c2c66affSColin Finck pContainer->file_size = 0;
701c2c66affSColin Finck pContainer->default_entry_type = default_entry_type;
702c2c66affSColin Finck
703c2c66affSColin Finck pContainer->path = heap_strdupW(path);
704c2c66affSColin Finck if (!pContainer->path)
705c2c66affSColin Finck {
706c2c66affSColin Finck heap_free(pContainer);
707c2c66affSColin Finck return FALSE;
708c2c66affSColin Finck }
709c2c66affSColin Finck
710c2c66affSColin Finck pContainer->cache_prefix = heap_alloc(cache_prefix_len+1);
711c2c66affSColin Finck if (!pContainer->cache_prefix)
712c2c66affSColin Finck {
713c2c66affSColin Finck heap_free(pContainer->path);
714c2c66affSColin Finck heap_free(pContainer);
715c2c66affSColin Finck return FALSE;
716c2c66affSColin Finck }
717c2c66affSColin Finck
718c2c66affSColin Finck memcpy(pContainer->cache_prefix, cache_prefix, cache_prefix_len+1);
719c2c66affSColin Finck
720c2c66affSColin Finck CharLowerW(mutex_name);
721c2c66affSColin Finck cache_container_create_object_name(mutex_name, '!');
722c2c66affSColin Finck
723c2c66affSColin Finck if ((pContainer->mutex = CreateMutexW(NULL, FALSE, mutex_name)) == NULL)
724c2c66affSColin Finck {
725c2c66affSColin Finck ERR("couldn't create mutex (error is %d)\n", GetLastError());
726c2c66affSColin Finck heap_free(pContainer->path);
727c2c66affSColin Finck heap_free(pContainer);
728c2c66affSColin Finck return FALSE;
729c2c66affSColin Finck }
730c2c66affSColin Finck
731c2c66affSColin Finck list_add_head(&UrlContainers, &pContainer->entry);
732c2c66affSColin Finck
733c2c66affSColin Finck return TRUE;
734c2c66affSColin Finck }
735c2c66affSColin Finck
cache_container_delete_container(cache_container * pContainer)736c2c66affSColin Finck static void cache_container_delete_container(cache_container *pContainer)
737c2c66affSColin Finck {
738c2c66affSColin Finck list_remove(&pContainer->entry);
739c2c66affSColin Finck
740c2c66affSColin Finck cache_container_close_index(pContainer);
741c2c66affSColin Finck CloseHandle(pContainer->mutex);
742c2c66affSColin Finck heap_free(pContainer->path);
743c2c66affSColin Finck heap_free(pContainer->cache_prefix);
744c2c66affSColin Finck heap_free(pContainer);
745c2c66affSColin Finck }
746c2c66affSColin Finck
cache_containers_init(void)747c2c66affSColin Finck static void cache_containers_init(void)
748c2c66affSColin Finck {
749c2c66affSColin Finck /* ReactOS r50916 */
750c2c66affSColin Finck static const struct
751c2c66affSColin Finck {
752c2c66affSColin Finck int nFolder; /* CSIDL_* constant */
753c2c66affSColin Finck const WCHAR *shpath_suffix; /* suffix on path returned by SHGetSpecialFolderPath */
754c2c66affSColin Finck const char *cache_prefix; /* prefix used to reference the container */
755c2c66affSColin Finck DWORD default_entry_type;
756c2c66affSColin Finck } DefaultContainerData[] =
757c2c66affSColin Finck {
758cde08ff2Swinesync { CSIDL_INTERNET_CACHE, L"Content.IE5", "", NORMAL_CACHE_ENTRY },
759cde08ff2Swinesync { CSIDL_HISTORY, L"History.IE5", "Visited:", URLHISTORY_CACHE_ENTRY },
760cde08ff2Swinesync { CSIDL_COOKIES, L"", "Cookie:", COOKIE_CACHE_ENTRY },
761c2c66affSColin Finck };
762c2c66affSColin Finck DWORD i;
763c2c66affSColin Finck
764c2c66affSColin Finck /* ReactOS r50916 */
765cde08ff2Swinesync if (GetEnvironmentVariableW(L"USERPROFILE", NULL, 0) == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND)
766c2c66affSColin Finck {
767c2c66affSColin Finck ERR("Environment variable 'USERPROFILE' does not exist!\n");
768c2c66affSColin Finck return;
769c2c66affSColin Finck }
770c2c66affSColin Finck
771c239cdd4SAmine Khaldi for (i = 0; i < ARRAY_SIZE(DefaultContainerData); i++)
772c2c66affSColin Finck {
773c2c66affSColin Finck WCHAR wszCachePath[MAX_PATH];
774c2c66affSColin Finck WCHAR wszMutexName[MAX_PATH];
775c2c66affSColin Finck int path_len, suffix_len;
776c2c66affSColin Finck BOOL def_char;
777c2c66affSColin Finck
778c2c66affSColin Finck if (!SHGetSpecialFolderPathW(NULL, wszCachePath, DefaultContainerData[i].nFolder, TRUE))
779c2c66affSColin Finck {
780c2c66affSColin Finck ERR("Couldn't get path for default container %u\n", i);
781c2c66affSColin Finck continue;
782c2c66affSColin Finck }
7835f12c8d7Swinesync path_len = lstrlenW(wszCachePath);
7845f12c8d7Swinesync suffix_len = lstrlenW(DefaultContainerData[i].shpath_suffix);
785c2c66affSColin Finck
786c2c66affSColin Finck if (path_len + suffix_len + 2 > MAX_PATH)
787c2c66affSColin Finck {
788c2c66affSColin Finck ERR("Path too long\n");
789c2c66affSColin Finck continue;
790c2c66affSColin Finck }
791c2c66affSColin Finck
792c2c66affSColin Finck wszCachePath[path_len] = '\\';
793c2c66affSColin Finck wszCachePath[path_len+1] = 0;
794c2c66affSColin Finck
7955f12c8d7Swinesync lstrcpyW(wszMutexName, wszCachePath);
796c2c66affSColin Finck
797c2c66affSColin Finck if (suffix_len)
798c2c66affSColin Finck {
799c2c66affSColin Finck memcpy(wszCachePath + path_len + 1, DefaultContainerData[i].shpath_suffix, (suffix_len + 1) * sizeof(WCHAR));
800c2c66affSColin Finck wszCachePath[path_len + suffix_len + 1] = '\\';
801c2c66affSColin Finck wszCachePath[path_len + suffix_len + 2] = '\0';
802c2c66affSColin Finck }
803c2c66affSColin Finck
804c2c66affSColin Finck if (!WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wszCachePath, path_len,
805c2c66affSColin Finck NULL, 0, NULL, &def_char) || def_char)
806c2c66affSColin Finck {
807c2c66affSColin Finck WCHAR tmp[MAX_PATH];
808c2c66affSColin Finck
809c2c66affSColin Finck /* cannot convert path to ANSI code page */
810c2c66affSColin Finck if (!(path_len = GetShortPathNameW(wszCachePath, tmp, MAX_PATH)) ||
811c2c66affSColin Finck !WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, tmp, path_len,
812c2c66affSColin Finck NULL, 0, NULL, &def_char) || def_char)
813c2c66affSColin Finck ERR("Can't create container path accessible by ANSI functions\n");
814c2c66affSColin Finck else
815c2c66affSColin Finck memcpy(wszCachePath, tmp, (path_len+1)*sizeof(WCHAR));
816c2c66affSColin Finck }
817c2c66affSColin Finck
818c2c66affSColin Finck cache_containers_add(DefaultContainerData[i].cache_prefix, wszCachePath,
819c2c66affSColin Finck DefaultContainerData[i].default_entry_type, wszMutexName);
820c2c66affSColin Finck }
821c2c66affSColin Finck
822c2c66affSColin Finck #ifdef __REACTOS__
823c2c66affSColin Finck bDefaultContainersAdded = TRUE;
824c2c66affSColin Finck #endif
825c2c66affSColin Finck }
826c2c66affSColin Finck
cache_containers_free(void)827c2c66affSColin Finck static void cache_containers_free(void)
828c2c66affSColin Finck {
829c2c66affSColin Finck while(!list_empty(&UrlContainers))
830c2c66affSColin Finck cache_container_delete_container(
831c2c66affSColin Finck LIST_ENTRY(list_head(&UrlContainers), cache_container, entry)
832c2c66affSColin Finck );
833c2c66affSColin Finck }
834c2c66affSColin Finck
cache_containers_find(const char * url,cache_container ** ret)835c2c66affSColin Finck static DWORD cache_containers_find(const char *url, cache_container **ret)
836c2c66affSColin Finck {
837c2c66affSColin Finck cache_container *container;
838c2c66affSColin Finck
839c2c66affSColin Finck TRACE("searching for prefix for URL: %s\n", debugstr_a(url));
840c2c66affSColin Finck
841c2c66affSColin Finck if(!url)
842c2c66affSColin Finck return ERROR_INVALID_PARAMETER;
843c2c66affSColin Finck
844c2c66affSColin Finck #ifdef __REACTOS__
845c2c66affSColin Finck /* ReactOS r54992 */
846c2c66affSColin Finck if (!bDefaultContainersAdded)
847c2c66affSColin Finck cache_containers_init();
848c2c66affSColin Finck #endif
849c2c66affSColin Finck
850c2c66affSColin Finck LIST_FOR_EACH_ENTRY(container, &UrlContainers, cache_container, entry)
851c2c66affSColin Finck {
852c2c66affSColin Finck int prefix_len = strlen(container->cache_prefix);
853c2c66affSColin Finck
854c2c66affSColin Finck if(!strncmp(container->cache_prefix, url, prefix_len)) {
855c2c66affSColin Finck TRACE("found container with prefix %s\n", debugstr_a(container->cache_prefix));
856c2c66affSColin Finck *ret = container;
857c2c66affSColin Finck return ERROR_SUCCESS;
858c2c66affSColin Finck }
859c2c66affSColin Finck }
860c2c66affSColin Finck
861c2c66affSColin Finck ERR("no container found\n");
862c2c66affSColin Finck return ERROR_FILE_NOT_FOUND;
863c2c66affSColin Finck }
864c2c66affSColin Finck
cache_containers_enum(char * search_pattern,DWORD index,cache_container ** ret)865c2c66affSColin Finck static BOOL cache_containers_enum(char *search_pattern, DWORD index, cache_container **ret)
866c2c66affSColin Finck {
867c2c66affSColin Finck DWORD i = 0;
868c2c66affSColin Finck cache_container *container;
869c2c66affSColin Finck
870c2c66affSColin Finck TRACE("searching for prefix: %s\n", debugstr_a(search_pattern));
871c2c66affSColin Finck
872c2c66affSColin Finck /* non-NULL search pattern only returns one container ever */
873c2c66affSColin Finck if (search_pattern && index > 0)
874c2c66affSColin Finck return FALSE;
875c2c66affSColin Finck
876c2c66affSColin Finck #ifdef __REACTOS__
877c2c66affSColin Finck /* ReactOS r54992 */
878c2c66affSColin Finck if (!bDefaultContainersAdded)
879c2c66affSColin Finck cache_containers_init();
880c2c66affSColin Finck #endif
881c2c66affSColin Finck
882c2c66affSColin Finck LIST_FOR_EACH_ENTRY(container, &UrlContainers, cache_container, entry)
883c2c66affSColin Finck {
884c2c66affSColin Finck if (search_pattern)
885c2c66affSColin Finck {
886c2c66affSColin Finck if (!strcmp(container->cache_prefix, search_pattern))
887c2c66affSColin Finck {
888c2c66affSColin Finck TRACE("found container with prefix %s\n", debugstr_a(container->cache_prefix));
889c2c66affSColin Finck *ret = container;
890c2c66affSColin Finck return TRUE;
891c2c66affSColin Finck }
892c2c66affSColin Finck }
893c2c66affSColin Finck else
894c2c66affSColin Finck {
895c2c66affSColin Finck if (i == index)
896c2c66affSColin Finck {
897c2c66affSColin Finck TRACE("found container with prefix %s\n", debugstr_a(container->cache_prefix));
898c2c66affSColin Finck *ret = container;
899c2c66affSColin Finck return TRUE;
900c2c66affSColin Finck }
901c2c66affSColin Finck }
902c2c66affSColin Finck i++;
903c2c66affSColin Finck }
904c2c66affSColin Finck return FALSE;
905c2c66affSColin Finck }
906c2c66affSColin Finck
907c2c66affSColin Finck /***********************************************************************
908c2c66affSColin Finck * cache_container_lock_index (Internal)
909c2c66affSColin Finck *
910c2c66affSColin Finck * Locks the index for system-wide exclusive access.
911c2c66affSColin Finck *
912c2c66affSColin Finck * RETURNS
913c2c66affSColin Finck * Cache file header if successful
914c2c66affSColin Finck * NULL if failed and calls SetLastError.
915c2c66affSColin Finck */
cache_container_lock_index(cache_container * pContainer)916c2c66affSColin Finck static urlcache_header* cache_container_lock_index(cache_container *pContainer)
917c2c66affSColin Finck {
918c2c66affSColin Finck BYTE index;
919c2c66affSColin Finck LPVOID pIndexData;
920c2c66affSColin Finck urlcache_header* pHeader;
921c2c66affSColin Finck DWORD error;
922c2c66affSColin Finck
923c2c66affSColin Finck /* acquire mutex */
924c2c66affSColin Finck WaitForSingleObject(pContainer->mutex, INFINITE);
925c2c66affSColin Finck
926c2c66affSColin Finck pIndexData = MapViewOfFile(pContainer->mapping, FILE_MAP_WRITE, 0, 0, 0);
927c2c66affSColin Finck
928c2c66affSColin Finck if (!pIndexData)
929c2c66affSColin Finck {
930c2c66affSColin Finck ReleaseMutex(pContainer->mutex);
931c2c66affSColin Finck ERR("Couldn't MapViewOfFile. Error: %d\n", GetLastError());
932c2c66affSColin Finck return NULL;
933c2c66affSColin Finck }
934c2c66affSColin Finck pHeader = (urlcache_header*)pIndexData;
935c2c66affSColin Finck
936c2c66affSColin Finck /* file has grown - we need to remap to prevent us getting
937c2c66affSColin Finck * access violations when we try and access beyond the end
938c2c66affSColin Finck * of the memory mapped file */
939c2c66affSColin Finck if (pHeader->size != pContainer->file_size)
940c2c66affSColin Finck {
941c2c66affSColin Finck UnmapViewOfFile( pHeader );
942c2c66affSColin Finck cache_container_close_index(pContainer);
943c2c66affSColin Finck error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
944c2c66affSColin Finck if (error != ERROR_SUCCESS)
945c2c66affSColin Finck {
946c2c66affSColin Finck ReleaseMutex(pContainer->mutex);
947c2c66affSColin Finck SetLastError(error);
948c2c66affSColin Finck return NULL;
949c2c66affSColin Finck }
950c2c66affSColin Finck pIndexData = MapViewOfFile(pContainer->mapping, FILE_MAP_WRITE, 0, 0, 0);
951c2c66affSColin Finck
952c2c66affSColin Finck if (!pIndexData)
953c2c66affSColin Finck {
954c2c66affSColin Finck ReleaseMutex(pContainer->mutex);
955c2c66affSColin Finck ERR("Couldn't MapViewOfFile. Error: %d\n", GetLastError());
956c2c66affSColin Finck return NULL;
957c2c66affSColin Finck }
958c2c66affSColin Finck pHeader = (urlcache_header*)pIndexData;
959c2c66affSColin Finck }
960c2c66affSColin Finck
961c2c66affSColin Finck TRACE("Signature: %s, file size: %d bytes\n", pHeader->signature, pHeader->size);
962c2c66affSColin Finck
963c2c66affSColin Finck for (index = 0; index < pHeader->dirs_no; index++)
964c2c66affSColin Finck {
965c2c66affSColin Finck TRACE("Directory[%d] = \"%.8s\"\n", index, pHeader->directory_data[index].name);
966c2c66affSColin Finck }
967c2c66affSColin Finck
968c2c66affSColin Finck return pHeader;
969c2c66affSColin Finck }
970c2c66affSColin Finck
971c2c66affSColin Finck /***********************************************************************
972c2c66affSColin Finck * cache_container_unlock_index (Internal)
973c2c66affSColin Finck *
974c2c66affSColin Finck */
cache_container_unlock_index(cache_container * pContainer,urlcache_header * pHeader)975c2c66affSColin Finck static BOOL cache_container_unlock_index(cache_container *pContainer, urlcache_header *pHeader)
976c2c66affSColin Finck {
977c2c66affSColin Finck /* release mutex */
978c2c66affSColin Finck ReleaseMutex(pContainer->mutex);
979c2c66affSColin Finck return UnmapViewOfFile(pHeader);
980c2c66affSColin Finck }
981c2c66affSColin Finck
982c2c66affSColin Finck /***********************************************************************
983c2c66affSColin Finck * urlcache_create_file_pathW (Internal)
984c2c66affSColin Finck *
985c2c66affSColin Finck * Copies the full path to the specified buffer given the local file
986c2c66affSColin Finck * name and the index of the directory it is in. Always sets value in
987c2c66affSColin Finck * lpBufferSize to the required buffer size (in bytes).
988c2c66affSColin Finck *
989c2c66affSColin Finck * RETURNS
990c2c66affSColin Finck * TRUE if the buffer was big enough
991c2c66affSColin Finck * FALSE if the buffer was too small
992c2c66affSColin Finck *
993c2c66affSColin Finck */
urlcache_create_file_pathW(const cache_container * pContainer,const urlcache_header * pHeader,LPCSTR szLocalFileName,BYTE Directory,LPWSTR wszPath,LPLONG lpBufferSize,BOOL trunc_name)994c2c66affSColin Finck static BOOL urlcache_create_file_pathW(
995c2c66affSColin Finck const cache_container *pContainer,
996c2c66affSColin Finck const urlcache_header *pHeader,
997c2c66affSColin Finck LPCSTR szLocalFileName,
998c2c66affSColin Finck BYTE Directory,
999c2c66affSColin Finck LPWSTR wszPath,
1000c2c66affSColin Finck LPLONG lpBufferSize,
1001c2c66affSColin Finck BOOL trunc_name)
1002c2c66affSColin Finck {
1003c2c66affSColin Finck LONG nRequired;
10045f12c8d7Swinesync int path_len = lstrlenW(pContainer->path);
1005c2c66affSColin Finck int file_name_len = MultiByteToWideChar(CP_ACP, 0, szLocalFileName, -1, NULL, 0);
1006c2c66affSColin Finck if (Directory!=CACHE_CONTAINER_NO_SUBDIR && Directory>=pHeader->dirs_no)
1007c2c66affSColin Finck {
1008c2c66affSColin Finck *lpBufferSize = 0;
1009c2c66affSColin Finck return FALSE;
1010c2c66affSColin Finck }
1011c2c66affSColin Finck
1012c2c66affSColin Finck nRequired = (path_len + file_name_len) * sizeof(WCHAR);
1013c2c66affSColin Finck if(Directory != CACHE_CONTAINER_NO_SUBDIR)
1014c2c66affSColin Finck nRequired += (DIR_LENGTH + 1) * sizeof(WCHAR);
1015c2c66affSColin Finck if (trunc_name && nRequired >= *lpBufferSize)
1016c2c66affSColin Finck nRequired = *lpBufferSize;
1017c2c66affSColin Finck if (nRequired <= *lpBufferSize)
1018c2c66affSColin Finck {
1019c2c66affSColin Finck int dir_len;
1020c2c66affSColin Finck
1021c2c66affSColin Finck memcpy(wszPath, pContainer->path, path_len * sizeof(WCHAR));
1022c2c66affSColin Finck if (Directory != CACHE_CONTAINER_NO_SUBDIR)
1023c2c66affSColin Finck {
1024c2c66affSColin Finck dir_len = MultiByteToWideChar(CP_ACP, 0, pHeader->directory_data[Directory].name, DIR_LENGTH, wszPath + path_len, DIR_LENGTH);
1025c2c66affSColin Finck wszPath[dir_len + path_len] = '\\';
1026c2c66affSColin Finck dir_len++;
1027c2c66affSColin Finck }
1028c2c66affSColin Finck else
1029c2c66affSColin Finck {
1030c2c66affSColin Finck dir_len = 0;
1031c2c66affSColin Finck }
1032c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, szLocalFileName, -1, wszPath + dir_len + path_len,
1033c2c66affSColin Finck *lpBufferSize/sizeof(WCHAR)-dir_len-path_len);
1034c2c66affSColin Finck wszPath[*lpBufferSize/sizeof(WCHAR)-1] = 0;
1035c2c66affSColin Finck *lpBufferSize = nRequired;
1036c2c66affSColin Finck return TRUE;
1037c2c66affSColin Finck }
1038c2c66affSColin Finck *lpBufferSize = nRequired;
1039c2c66affSColin Finck return FALSE;
1040c2c66affSColin Finck }
1041c2c66affSColin Finck
1042c2c66affSColin Finck /***********************************************************************
1043c2c66affSColin Finck * urlcache_create_file_pathA (Internal)
1044c2c66affSColin Finck *
1045c2c66affSColin Finck * Copies the full path to the specified buffer given the local file
1046c2c66affSColin Finck * name and the index of the directory it is in. Always sets value in
1047c2c66affSColin Finck * lpBufferSize to the required buffer size.
1048c2c66affSColin Finck *
1049c2c66affSColin Finck * RETURNS
1050c2c66affSColin Finck * TRUE if the buffer was big enough
1051c2c66affSColin Finck * FALSE if the buffer was too small
1052c2c66affSColin Finck *
1053c2c66affSColin Finck */
urlcache_create_file_pathA(const cache_container * pContainer,const urlcache_header * pHeader,LPCSTR szLocalFileName,BYTE Directory,LPSTR szPath,LPLONG lpBufferSize)1054c2c66affSColin Finck static BOOL urlcache_create_file_pathA(
1055c2c66affSColin Finck const cache_container *pContainer,
1056c2c66affSColin Finck const urlcache_header *pHeader,
1057c2c66affSColin Finck LPCSTR szLocalFileName,
1058c2c66affSColin Finck BYTE Directory,
1059c2c66affSColin Finck LPSTR szPath,
1060c2c66affSColin Finck LPLONG lpBufferSize)
1061c2c66affSColin Finck {
1062c2c66affSColin Finck LONG nRequired;
1063c2c66affSColin Finck int path_len, file_name_len, dir_len;
1064c2c66affSColin Finck
1065c2c66affSColin Finck if (Directory!=CACHE_CONTAINER_NO_SUBDIR && Directory>=pHeader->dirs_no)
1066c2c66affSColin Finck {
1067c2c66affSColin Finck *lpBufferSize = 0;
1068c2c66affSColin Finck return FALSE;
1069c2c66affSColin Finck }
1070c2c66affSColin Finck
1071c2c66affSColin Finck path_len = WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, NULL, 0, NULL, NULL) - 1;
1072c2c66affSColin Finck file_name_len = strlen(szLocalFileName) + 1 /* for nul-terminator */;
1073c2c66affSColin Finck if (Directory!=CACHE_CONTAINER_NO_SUBDIR)
1074c2c66affSColin Finck dir_len = DIR_LENGTH+1;
1075c2c66affSColin Finck else
1076c2c66affSColin Finck dir_len = 0;
1077c2c66affSColin Finck
1078c2c66affSColin Finck nRequired = (path_len + dir_len + file_name_len) * sizeof(char);
1079c2c66affSColin Finck if (nRequired <= *lpBufferSize)
1080c2c66affSColin Finck {
1081c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, szPath, path_len, NULL, NULL);
1082c2c66affSColin Finck if(dir_len) {
1083c2c66affSColin Finck memcpy(szPath+path_len, pHeader->directory_data[Directory].name, dir_len-1);
1084c2c66affSColin Finck szPath[path_len + dir_len-1] = '\\';
1085c2c66affSColin Finck }
1086c2c66affSColin Finck memcpy(szPath + path_len + dir_len, szLocalFileName, file_name_len);
1087c2c66affSColin Finck *lpBufferSize = nRequired;
1088c2c66affSColin Finck return TRUE;
1089c2c66affSColin Finck }
1090c2c66affSColin Finck *lpBufferSize = nRequired;
1091c2c66affSColin Finck return FALSE;
1092c2c66affSColin Finck }
1093c2c66affSColin Finck
1094c2c66affSColin Finck /* Just like FileTimeToDosDateTime, except that it also maps the special
1095c2c66affSColin Finck * case of a filetime of (0,0) to a DOS date/time of (0,0).
1096c2c66affSColin Finck */
file_time_to_dos_date_time(const FILETIME * ft,WORD * fatdate,WORD * fattime)1097c2c66affSColin Finck static void file_time_to_dos_date_time(const FILETIME *ft, WORD *fatdate,
1098c2c66affSColin Finck WORD *fattime)
1099c2c66affSColin Finck {
1100c2c66affSColin Finck if (!ft->dwLowDateTime && !ft->dwHighDateTime)
1101c2c66affSColin Finck *fatdate = *fattime = 0;
1102c2c66affSColin Finck else
1103c2c66affSColin Finck FileTimeToDosDateTime(ft, fatdate, fattime);
1104c2c66affSColin Finck }
1105c2c66affSColin Finck
1106c2c66affSColin Finck /***********************************************************************
1107c2c66affSColin Finck * urlcache_delete_file (Internal)
1108c2c66affSColin Finck */
urlcache_delete_file(const cache_container * container,urlcache_header * header,entry_url * url_entry)1109c2c66affSColin Finck static DWORD urlcache_delete_file(const cache_container *container,
1110c2c66affSColin Finck urlcache_header *header, entry_url *url_entry)
1111c2c66affSColin Finck {
1112c2c66affSColin Finck WIN32_FILE_ATTRIBUTE_DATA attr;
1113c2c66affSColin Finck WCHAR path[MAX_PATH];
1114c2c66affSColin Finck LONG path_size = sizeof(path);
1115c2c66affSColin Finck DWORD err;
1116c2c66affSColin Finck WORD date, time;
1117c2c66affSColin Finck
1118c2c66affSColin Finck if(!url_entry->local_name_off)
1119c2c66affSColin Finck goto succ;
1120c2c66affSColin Finck
1121c2c66affSColin Finck if(!urlcache_create_file_pathW(container, header,
1122c2c66affSColin Finck (LPCSTR)url_entry+url_entry->local_name_off,
1123c2c66affSColin Finck url_entry->cache_dir, path, &path_size, FALSE))
1124c2c66affSColin Finck goto succ;
1125c2c66affSColin Finck
1126c2c66affSColin Finck if(!GetFileAttributesExW(path, GetFileExInfoStandard, &attr))
1127c2c66affSColin Finck goto succ;
1128c2c66affSColin Finck file_time_to_dos_date_time(&attr.ftLastWriteTime, &date, &time);
1129c2c66affSColin Finck if(date != url_entry->write_date || time != url_entry->write_time)
1130c2c66affSColin Finck goto succ;
1131c2c66affSColin Finck
1132c2c66affSColin Finck err = (DeleteFileW(path) ? ERROR_SUCCESS : GetLastError());
1133c2c66affSColin Finck if(err == ERROR_ACCESS_DENIED || err == ERROR_SHARING_VIOLATION)
1134c2c66affSColin Finck return err;
1135c2c66affSColin Finck
1136c2c66affSColin Finck succ:
1137c2c66affSColin Finck if (url_entry->cache_dir < header->dirs_no)
1138c2c66affSColin Finck {
1139c2c66affSColin Finck if (header->directory_data[url_entry->cache_dir].files_no)
1140c2c66affSColin Finck header->directory_data[url_entry->cache_dir].files_no--;
1141c2c66affSColin Finck }
1142c2c66affSColin Finck if (url_entry->cache_entry_type & STICKY_CACHE_ENTRY)
1143c2c66affSColin Finck {
1144c2c66affSColin Finck if (url_entry->size.QuadPart < header->exempt_usage.QuadPart)
1145c2c66affSColin Finck header->exempt_usage.QuadPart -= url_entry->size.QuadPart;
1146c2c66affSColin Finck else
1147c2c66affSColin Finck header->exempt_usage.QuadPart = 0;
1148c2c66affSColin Finck }
1149c2c66affSColin Finck else
1150c2c66affSColin Finck {
1151c2c66affSColin Finck if (url_entry->size.QuadPart < header->cache_usage.QuadPart)
1152c2c66affSColin Finck header->cache_usage.QuadPart -= url_entry->size.QuadPart;
1153c2c66affSColin Finck else
1154c2c66affSColin Finck header->cache_usage.QuadPart = 0;
1155c2c66affSColin Finck }
1156c2c66affSColin Finck
1157c2c66affSColin Finck return ERROR_SUCCESS;
1158c2c66affSColin Finck }
1159c2c66affSColin Finck
urlcache_clean_leaked_entries(cache_container * container,urlcache_header * header)1160c2c66affSColin Finck static BOOL urlcache_clean_leaked_entries(cache_container *container, urlcache_header *header)
1161c2c66affSColin Finck {
1162c2c66affSColin Finck DWORD *leak_off;
1163c2c66affSColin Finck BOOL freed = FALSE;
1164c2c66affSColin Finck
1165c2c66affSColin Finck leak_off = &header->options[CACHE_HEADER_DATA_ROOT_LEAK_OFFSET];
1166c2c66affSColin Finck while(*leak_off) {
1167c2c66affSColin Finck entry_url *url_entry = (entry_url*)((LPBYTE)header + *leak_off);
1168c2c66affSColin Finck
1169c2c66affSColin Finck if(SUCCEEDED(urlcache_delete_file(container, header, url_entry))) {
1170c2c66affSColin Finck *leak_off = url_entry->exempt_delta;
1171c2c66affSColin Finck urlcache_entry_free(header, &url_entry->header);
1172c2c66affSColin Finck freed = TRUE;
1173c2c66affSColin Finck }else {
1174c2c66affSColin Finck leak_off = &url_entry->exempt_delta;
1175c2c66affSColin Finck }
1176c2c66affSColin Finck }
1177c2c66affSColin Finck
1178c2c66affSColin Finck return freed;
1179c2c66affSColin Finck }
1180c2c66affSColin Finck
1181c2c66affSColin Finck /***********************************************************************
1182c2c66affSColin Finck * cache_container_clean_index (Internal)
1183c2c66affSColin Finck *
1184c2c66affSColin Finck * This function is meant to make place in index file by removing leaked
1185c2c66affSColin Finck * files entries and resizing the file.
1186c2c66affSColin Finck *
1187c2c66affSColin Finck * CAUTION: file view may get mapped to new memory
1188c2c66affSColin Finck *
1189c2c66affSColin Finck * RETURNS
1190c2c66affSColin Finck * ERROR_SUCCESS when new memory is available
1191c2c66affSColin Finck * error code otherwise
1192c2c66affSColin Finck */
cache_container_clean_index(cache_container * container,urlcache_header ** file_view)1193c2c66affSColin Finck static DWORD cache_container_clean_index(cache_container *container, urlcache_header **file_view)
1194c2c66affSColin Finck {
1195c2c66affSColin Finck urlcache_header *header = *file_view;
1196c2c66affSColin Finck DWORD ret;
1197c2c66affSColin Finck
1198c2c66affSColin Finck TRACE("(%s %s)\n", debugstr_a(container->cache_prefix), debugstr_w(container->path));
1199c2c66affSColin Finck
1200c2c66affSColin Finck if(urlcache_clean_leaked_entries(container, header))
1201c2c66affSColin Finck return ERROR_SUCCESS;
1202c2c66affSColin Finck
1203c2c66affSColin Finck if(header->size >= ALLOCATION_TABLE_SIZE*8*BLOCKSIZE + ENTRY_START_OFFSET) {
1204c2c66affSColin Finck WARN("index file has maximal size\n");
1205c2c66affSColin Finck return ERROR_NOT_ENOUGH_MEMORY;
1206c2c66affSColin Finck }
1207c2c66affSColin Finck
1208c2c66affSColin Finck cache_container_close_index(container);
1209c2c66affSColin Finck ret = cache_container_open_index(container, header->capacity_in_blocks*2);
1210c2c66affSColin Finck if(ret != ERROR_SUCCESS)
1211c2c66affSColin Finck return ret;
1212c2c66affSColin Finck header = MapViewOfFile(container->mapping, FILE_MAP_WRITE, 0, 0, 0);
1213c2c66affSColin Finck if(!header)
1214c2c66affSColin Finck return GetLastError();
1215c2c66affSColin Finck
1216c2c66affSColin Finck UnmapViewOfFile(*file_view);
1217c2c66affSColin Finck *file_view = header;
1218c2c66affSColin Finck return ERROR_SUCCESS;
1219c2c66affSColin Finck }
1220c2c66affSColin Finck
1221c2c66affSColin Finck /* Just like DosDateTimeToFileTime, except that it also maps the special
1222c2c66affSColin Finck * case of a DOS date/time of (0,0) to a filetime of (0,0).
1223c2c66affSColin Finck */
dos_date_time_to_file_time(WORD fatdate,WORD fattime,FILETIME * ft)1224c2c66affSColin Finck static void dos_date_time_to_file_time(WORD fatdate, WORD fattime,
1225c2c66affSColin Finck FILETIME *ft)
1226c2c66affSColin Finck {
1227c2c66affSColin Finck if (!fatdate && !fattime)
1228c2c66affSColin Finck ft->dwLowDateTime = ft->dwHighDateTime = 0;
1229c2c66affSColin Finck else
1230c2c66affSColin Finck DosDateTimeToFileTime(fatdate, fattime, ft);
1231c2c66affSColin Finck }
1232c2c66affSColin Finck
urlcache_decode_url(const char * url,WCHAR * decoded_url,int decoded_len)1233c2c66affSColin Finck static int urlcache_decode_url(const char *url, WCHAR *decoded_url, int decoded_len)
1234c2c66affSColin Finck {
1235c2c66affSColin Finck URL_COMPONENTSA uc;
1236c2c66affSColin Finck DWORD len, part_len;
1237c2c66affSColin Finck WCHAR *host_name;
1238c2c66affSColin Finck
1239c2c66affSColin Finck memset(&uc, 0, sizeof(uc));
1240c2c66affSColin Finck uc.dwStructSize = sizeof(uc);
1241c2c66affSColin Finck uc.dwHostNameLength = 1;
1242c2c66affSColin Finck if(!InternetCrackUrlA(url, 0, 0, &uc))
1243c2c66affSColin Finck uc.nScheme = INTERNET_SCHEME_UNKNOWN;
1244c2c66affSColin Finck
1245c2c66affSColin Finck if(uc.nScheme!=INTERNET_SCHEME_HTTP && uc.nScheme!=INTERNET_SCHEME_HTTPS)
1246c2c66affSColin Finck return MultiByteToWideChar(CP_UTF8, 0, url, -1, decoded_url, decoded_len);
1247c2c66affSColin Finck
1248c2c66affSColin Finck if(!decoded_url)
1249c2c66affSColin Finck decoded_len = 0;
1250c2c66affSColin Finck
1251c2c66affSColin Finck len = MultiByteToWideChar(CP_UTF8, 0, url, uc.lpszHostName-url, decoded_url, decoded_len);
1252c2c66affSColin Finck if(!len)
1253c2c66affSColin Finck return 0;
1254c2c66affSColin Finck if(decoded_url)
1255c2c66affSColin Finck decoded_len -= len;
1256c2c66affSColin Finck
1257c2c66affSColin Finck host_name = heap_alloc(uc.dwHostNameLength*sizeof(WCHAR));
1258c2c66affSColin Finck if(!host_name)
1259c2c66affSColin Finck return 0;
1260c2c66affSColin Finck if(!MultiByteToWideChar(CP_UTF8, 0, uc.lpszHostName, uc.dwHostNameLength,
1261c2c66affSColin Finck host_name, uc.dwHostNameLength)) {
1262c2c66affSColin Finck heap_free(host_name);
1263c2c66affSColin Finck return 0;
1264c2c66affSColin Finck }
1265c2c66affSColin Finck part_len = IdnToUnicode(0, host_name, uc.dwHostNameLength,
1266c2c66affSColin Finck decoded_url ? decoded_url+len : NULL, decoded_len);
1267c2c66affSColin Finck heap_free(host_name);
1268c2c66affSColin Finck if(!part_len) {
1269c2c66affSColin Finck SetLastError(ERROR_INTERNET_INVALID_URL);
1270c2c66affSColin Finck return 0;
1271c2c66affSColin Finck }
1272c2c66affSColin Finck len += part_len;
1273c2c66affSColin Finck if(decoded_url)
1274c2c66affSColin Finck decoded_len -= part_len;
1275c2c66affSColin Finck
1276c2c66affSColin Finck part_len = MultiByteToWideChar(CP_UTF8, 0,
1277c2c66affSColin Finck uc.lpszHostName+uc.dwHostNameLength,
1278c2c66affSColin Finck -1, decoded_url ? decoded_url+len : NULL, decoded_len);
1279c2c66affSColin Finck if(!part_len)
1280c2c66affSColin Finck return 0;
1281c2c66affSColin Finck len += part_len;
1282c2c66affSColin Finck
1283c2c66affSColin Finck return len;
1284c2c66affSColin Finck }
1285c2c66affSColin Finck
1286c2c66affSColin Finck /***********************************************************************
1287c2c66affSColin Finck * urlcache_copy_entry (Internal)
1288c2c66affSColin Finck *
1289c2c66affSColin Finck * Copies an entry from the cache index file to the Win32 structure
1290c2c66affSColin Finck *
1291c2c66affSColin Finck * RETURNS
1292c2c66affSColin Finck * ERROR_SUCCESS if the buffer was big enough
1293c2c66affSColin Finck * ERROR_INSUFFICIENT_BUFFER if the buffer was too small
1294c2c66affSColin Finck *
1295c2c66affSColin Finck */
urlcache_copy_entry(cache_container * container,const urlcache_header * header,INTERNET_CACHE_ENTRY_INFOA * entry_info,DWORD * info_size,const entry_url * url_entry,BOOL unicode)1296c2c66affSColin Finck static DWORD urlcache_copy_entry(cache_container *container, const urlcache_header *header,
1297c2c66affSColin Finck INTERNET_CACHE_ENTRY_INFOA *entry_info, DWORD *info_size, const entry_url *url_entry, BOOL unicode)
1298c2c66affSColin Finck {
1299c2c66affSColin Finck int url_len;
1300c2c66affSColin Finck DWORD size = sizeof(*entry_info);
1301c2c66affSColin Finck
1302c2c66affSColin Finck if(*info_size >= size) {
1303c2c66affSColin Finck entry_info->lpHeaderInfo = NULL;
1304c2c66affSColin Finck entry_info->lpszFileExtension = NULL;
1305c2c66affSColin Finck entry_info->lpszLocalFileName = NULL;
1306c2c66affSColin Finck entry_info->lpszSourceUrlName = NULL;
1307c2c66affSColin Finck entry_info->CacheEntryType = url_entry->cache_entry_type;
1308c2c66affSColin Finck entry_info->u.dwExemptDelta = url_entry->exempt_delta;
1309c2c66affSColin Finck entry_info->dwHeaderInfoSize = url_entry->header_info_size;
1310c2c66affSColin Finck entry_info->dwHitRate = url_entry->hit_rate;
1311c2c66affSColin Finck entry_info->dwSizeHigh = url_entry->size.u.HighPart;
1312c2c66affSColin Finck entry_info->dwSizeLow = url_entry->size.u.LowPart;
1313c2c66affSColin Finck entry_info->dwStructSize = sizeof(*entry_info);
1314c2c66affSColin Finck entry_info->dwUseCount = url_entry->use_count;
1315c2c66affSColin Finck dos_date_time_to_file_time(url_entry->expire_date, url_entry->expire_time, &entry_info->ExpireTime);
1316c2c66affSColin Finck entry_info->LastAccessTime = url_entry->access_time;
1317c2c66affSColin Finck entry_info->LastModifiedTime = url_entry->modification_time;
1318c2c66affSColin Finck dos_date_time_to_file_time(url_entry->sync_date, url_entry->sync_time, &entry_info->LastSyncTime);
1319c2c66affSColin Finck }
1320c2c66affSColin Finck
1321c2c66affSColin Finck if(unicode)
1322c2c66affSColin Finck url_len = urlcache_decode_url((const char*)url_entry+url_entry->url_off, NULL, 0);
1323c2c66affSColin Finck else
1324c2c66affSColin Finck url_len = strlen((LPCSTR)url_entry+url_entry->url_off) + 1;
1325c2c66affSColin Finck size += url_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
1326c2c66affSColin Finck
1327c2c66affSColin Finck if(*info_size >= size) {
1328c2c66affSColin Finck DWORD url_size = url_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
1329c2c66affSColin Finck
1330c2c66affSColin Finck entry_info->lpszSourceUrlName = (LPSTR)entry_info+size-url_size;
1331c2c66affSColin Finck if(unicode)
1332c2c66affSColin Finck urlcache_decode_url((const char*)url_entry+url_entry->url_off, (WCHAR*)entry_info->lpszSourceUrlName, url_len);
1333c2c66affSColin Finck else
1334c2c66affSColin Finck memcpy(entry_info->lpszSourceUrlName, (LPCSTR)url_entry+url_entry->url_off, url_size);
1335c2c66affSColin Finck }
1336c2c66affSColin Finck
1337c2c66affSColin Finck if(size%4 && size<*info_size)
1338c2c66affSColin Finck ZeroMemory((LPBYTE)entry_info+size, 4-size%4);
1339c2c66affSColin Finck size = DWORD_ALIGN(size);
1340c2c66affSColin Finck
1341c2c66affSColin Finck if(url_entry->local_name_off) {
1342c2c66affSColin Finck LONG file_name_size;
1343c2c66affSColin Finck LPSTR file_name;
1344c2c66affSColin Finck file_name = (LPSTR)entry_info+size;
1345c2c66affSColin Finck file_name_size = *info_size-size;
1346c2c66affSColin Finck if((unicode && urlcache_create_file_pathW(container, header, (LPCSTR)url_entry+url_entry->local_name_off,
1347c2c66affSColin Finck url_entry->cache_dir, (LPWSTR)file_name, &file_name_size, FALSE)) ||
1348c2c66affSColin Finck (!unicode && urlcache_create_file_pathA(container, header, (LPCSTR)url_entry+url_entry->local_name_off,
1349c2c66affSColin Finck url_entry->cache_dir, file_name, &file_name_size))) {
1350c2c66affSColin Finck entry_info->lpszLocalFileName = file_name;
1351c2c66affSColin Finck }
1352c2c66affSColin Finck size += file_name_size;
1353c2c66affSColin Finck
1354c2c66affSColin Finck if(size%4 && size<*info_size)
1355c2c66affSColin Finck ZeroMemory((LPBYTE)entry_info+size, 4-size%4);
1356c2c66affSColin Finck size = DWORD_ALIGN(size);
1357c2c66affSColin Finck }
1358c2c66affSColin Finck
1359c2c66affSColin Finck if(url_entry->header_info_off) {
1360c2c66affSColin Finck DWORD header_len;
1361c2c66affSColin Finck
1362c2c66affSColin Finck if(unicode)
1363c2c66affSColin Finck header_len = MultiByteToWideChar(CP_UTF8, 0, (const char*)url_entry+url_entry->header_info_off,
1364c2c66affSColin Finck url_entry->header_info_size, NULL, 0);
1365c2c66affSColin Finck else
1366c2c66affSColin Finck header_len = url_entry->header_info_size;
1367c2c66affSColin Finck size += header_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
1368c2c66affSColin Finck
1369c2c66affSColin Finck if(*info_size >= size) {
1370c2c66affSColin Finck DWORD header_size = header_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
1371c2c66affSColin Finck entry_info->lpHeaderInfo = (LPBYTE)entry_info+size-header_size;
1372c2c66affSColin Finck if(unicode)
1373c2c66affSColin Finck MultiByteToWideChar(CP_UTF8, 0, (const char*)url_entry+url_entry->header_info_off,
1374c2c66affSColin Finck url_entry->header_info_size, (LPWSTR)entry_info->lpHeaderInfo, header_len);
1375c2c66affSColin Finck else
1376c2c66affSColin Finck memcpy(entry_info->lpHeaderInfo, (LPCSTR)url_entry+url_entry->header_info_off, header_len);
1377c2c66affSColin Finck }
1378c2c66affSColin Finck if(size%4 && size<*info_size)
1379c2c66affSColin Finck ZeroMemory((LPBYTE)entry_info+size, 4-size%4);
1380c2c66affSColin Finck size = DWORD_ALIGN(size);
1381c2c66affSColin Finck }
1382c2c66affSColin Finck
1383c2c66affSColin Finck if(url_entry->file_extension_off) {
1384c2c66affSColin Finck int ext_len;
1385c2c66affSColin Finck
1386c2c66affSColin Finck if(unicode)
1387c2c66affSColin Finck ext_len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)url_entry+url_entry->file_extension_off, -1, NULL, 0);
1388c2c66affSColin Finck else
1389c2c66affSColin Finck ext_len = strlen((LPCSTR)url_entry+url_entry->file_extension_off) + 1;
1390c2c66affSColin Finck size += ext_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
1391c2c66affSColin Finck
1392c2c66affSColin Finck if(*info_size >= size) {
1393c2c66affSColin Finck DWORD ext_size = ext_len * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
1394c2c66affSColin Finck entry_info->lpszFileExtension = (LPSTR)entry_info+size-ext_size;
1395c2c66affSColin Finck if(unicode)
1396c2c66affSColin Finck MultiByteToWideChar(CP_ACP, 0, (LPCSTR)url_entry+url_entry->file_extension_off, -1, (LPWSTR)entry_info->lpszFileExtension, ext_len);
1397c2c66affSColin Finck else
1398c2c66affSColin Finck memcpy(entry_info->lpszFileExtension, (LPCSTR)url_entry+url_entry->file_extension_off, ext_len*sizeof(CHAR));
1399c2c66affSColin Finck }
1400c2c66affSColin Finck
1401c2c66affSColin Finck if(size%4 && size<*info_size)
1402c2c66affSColin Finck ZeroMemory((LPBYTE)entry_info+size, 4-size%4);
1403c2c66affSColin Finck size = DWORD_ALIGN(size);
1404c2c66affSColin Finck }
1405c2c66affSColin Finck
1406c2c66affSColin Finck if(size > *info_size) {
1407c2c66affSColin Finck *info_size = size;
1408c2c66affSColin Finck return ERROR_INSUFFICIENT_BUFFER;
1409c2c66affSColin Finck }
1410c2c66affSColin Finck *info_size = size;
1411c2c66affSColin Finck return ERROR_SUCCESS;
1412c2c66affSColin Finck }
1413c2c66affSColin Finck
1414c2c66affSColin Finck /***********************************************************************
1415c2c66affSColin Finck * urlcache_set_entry_info (Internal)
1416c2c66affSColin Finck *
1417c2c66affSColin Finck * Helper for SetUrlCacheEntryInfo{A,W}. Sets fields in URL entry
1418c2c66affSColin Finck * according to the flags set by field_control.
1419c2c66affSColin Finck *
1420c2c66affSColin Finck * RETURNS
1421c2c66affSColin Finck * ERROR_SUCCESS if the buffer was big enough
1422c2c66affSColin Finck * ERROR_INSUFFICIENT_BUFFER if the buffer was too small
1423c2c66affSColin Finck *
1424c2c66affSColin Finck */
urlcache_set_entry_info(entry_url * url_entry,const INTERNET_CACHE_ENTRY_INFOA * entry_info,DWORD field_control)1425c2c66affSColin Finck static DWORD urlcache_set_entry_info(entry_url *url_entry, const INTERNET_CACHE_ENTRY_INFOA *entry_info, DWORD field_control)
1426c2c66affSColin Finck {
1427c2c66affSColin Finck if (field_control & CACHE_ENTRY_ACCTIME_FC)
1428c2c66affSColin Finck url_entry->access_time = entry_info->LastAccessTime;
1429c2c66affSColin Finck if (field_control & CACHE_ENTRY_ATTRIBUTE_FC)
1430c2c66affSColin Finck url_entry->cache_entry_type = entry_info->CacheEntryType;
1431c2c66affSColin Finck if (field_control & CACHE_ENTRY_EXEMPT_DELTA_FC)
1432c2c66affSColin Finck url_entry->exempt_delta = entry_info->u.dwExemptDelta;
1433c2c66affSColin Finck if (field_control & CACHE_ENTRY_EXPTIME_FC)
1434c2c66affSColin Finck file_time_to_dos_date_time(&entry_info->ExpireTime, &url_entry->expire_date, &url_entry->expire_time);
1435c2c66affSColin Finck if (field_control & CACHE_ENTRY_HEADERINFO_FC)
1436c2c66affSColin Finck FIXME("CACHE_ENTRY_HEADERINFO_FC unimplemented\n");
1437c2c66affSColin Finck if (field_control & CACHE_ENTRY_HITRATE_FC)
1438c2c66affSColin Finck url_entry->hit_rate = entry_info->dwHitRate;
1439c2c66affSColin Finck if (field_control & CACHE_ENTRY_MODTIME_FC)
1440c2c66affSColin Finck url_entry->modification_time = entry_info->LastModifiedTime;
1441c2c66affSColin Finck if (field_control & CACHE_ENTRY_SYNCTIME_FC)
1442c2c66affSColin Finck file_time_to_dos_date_time(&entry_info->LastAccessTime, &url_entry->sync_date, &url_entry->sync_time);
1443c2c66affSColin Finck
1444c2c66affSColin Finck return ERROR_SUCCESS;
1445c2c66affSColin Finck }
1446c2c66affSColin Finck
1447c2c66affSColin Finck /***********************************************************************
1448c2c66affSColin Finck * urlcache_hash_key (Internal)
1449c2c66affSColin Finck *
1450c2c66affSColin Finck * Returns the hash key for a given string
1451c2c66affSColin Finck *
1452c2c66affSColin Finck * RETURNS
1453c2c66affSColin Finck * hash key for the string
1454c2c66affSColin Finck *
1455c2c66affSColin Finck */
urlcache_hash_key(LPCSTR lpszKey)1456c2c66affSColin Finck static DWORD urlcache_hash_key(LPCSTR lpszKey)
1457c2c66affSColin Finck {
1458c2c66affSColin Finck /* NOTE: this uses the same lookup table as SHLWAPI.UrlHash{A,W}
1459c2c66affSColin Finck * but the algorithm and result are not the same!
1460c2c66affSColin Finck */
1461c2c66affSColin Finck static const unsigned char lookupTable[256] =
1462c2c66affSColin Finck {
1463c2c66affSColin Finck 0x01, 0x0E, 0x6E, 0x19, 0x61, 0xAE, 0x84, 0x77,
1464c2c66affSColin Finck 0x8A, 0xAA, 0x7D, 0x76, 0x1B, 0xE9, 0x8C, 0x33,
1465c2c66affSColin Finck 0x57, 0xC5, 0xB1, 0x6B, 0xEA, 0xA9, 0x38, 0x44,
1466c2c66affSColin Finck 0x1E, 0x07, 0xAD, 0x49, 0xBC, 0x28, 0x24, 0x41,
1467c2c66affSColin Finck 0x31, 0xD5, 0x68, 0xBE, 0x39, 0xD3, 0x94, 0xDF,
1468c2c66affSColin Finck 0x30, 0x73, 0x0F, 0x02, 0x43, 0xBA, 0xD2, 0x1C,
1469c2c66affSColin Finck 0x0C, 0xB5, 0x67, 0x46, 0x16, 0x3A, 0x4B, 0x4E,
1470c2c66affSColin Finck 0xB7, 0xA7, 0xEE, 0x9D, 0x7C, 0x93, 0xAC, 0x90,
1471c2c66affSColin Finck 0xB0, 0xA1, 0x8D, 0x56, 0x3C, 0x42, 0x80, 0x53,
1472c2c66affSColin Finck 0x9C, 0xF1, 0x4F, 0x2E, 0xA8, 0xC6, 0x29, 0xFE,
1473c2c66affSColin Finck 0xB2, 0x55, 0xFD, 0xED, 0xFA, 0x9A, 0x85, 0x58,
1474c2c66affSColin Finck 0x23, 0xCE, 0x5F, 0x74, 0xFC, 0xC0, 0x36, 0xDD,
1475c2c66affSColin Finck 0x66, 0xDA, 0xFF, 0xF0, 0x52, 0x6A, 0x9E, 0xC9,
1476c2c66affSColin Finck 0x3D, 0x03, 0x59, 0x09, 0x2A, 0x9B, 0x9F, 0x5D,
1477c2c66affSColin Finck 0xA6, 0x50, 0x32, 0x22, 0xAF, 0xC3, 0x64, 0x63,
1478c2c66affSColin Finck 0x1A, 0x96, 0x10, 0x91, 0x04, 0x21, 0x08, 0xBD,
1479c2c66affSColin Finck 0x79, 0x40, 0x4D, 0x48, 0xD0, 0xF5, 0x82, 0x7A,
1480c2c66affSColin Finck 0x8F, 0x37, 0x69, 0x86, 0x1D, 0xA4, 0xB9, 0xC2,
1481c2c66affSColin Finck 0xC1, 0xEF, 0x65, 0xF2, 0x05, 0xAB, 0x7E, 0x0B,
1482c2c66affSColin Finck 0x4A, 0x3B, 0x89, 0xE4, 0x6C, 0xBF, 0xE8, 0x8B,
1483c2c66affSColin Finck 0x06, 0x18, 0x51, 0x14, 0x7F, 0x11, 0x5B, 0x5C,
1484c2c66affSColin Finck 0xFB, 0x97, 0xE1, 0xCF, 0x15, 0x62, 0x71, 0x70,
1485c2c66affSColin Finck 0x54, 0xE2, 0x12, 0xD6, 0xC7, 0xBB, 0x0D, 0x20,
1486c2c66affSColin Finck 0x5E, 0xDC, 0xE0, 0xD4, 0xF7, 0xCC, 0xC4, 0x2B,
1487c2c66affSColin Finck 0xF9, 0xEC, 0x2D, 0xF4, 0x6F, 0xB6, 0x99, 0x88,
1488c2c66affSColin Finck 0x81, 0x5A, 0xD9, 0xCA, 0x13, 0xA5, 0xE7, 0x47,
1489c2c66affSColin Finck 0xE6, 0x8E, 0x60, 0xE3, 0x3E, 0xB3, 0xF6, 0x72,
1490c2c66affSColin Finck 0xA2, 0x35, 0xA0, 0xD7, 0xCD, 0xB4, 0x2F, 0x6D,
1491c2c66affSColin Finck 0x2C, 0x26, 0x1F, 0x95, 0x87, 0x00, 0xD8, 0x34,
1492c2c66affSColin Finck 0x3F, 0x17, 0x25, 0x45, 0x27, 0x75, 0x92, 0xB8,
1493c2c66affSColin Finck 0xA3, 0xC8, 0xDE, 0xEB, 0xF8, 0xF3, 0xDB, 0x0A,
1494c2c66affSColin Finck 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1
1495c2c66affSColin Finck };
1496c2c66affSColin Finck BYTE key[4];
1497c2c66affSColin Finck DWORD i;
1498c2c66affSColin Finck
1499c239cdd4SAmine Khaldi for (i = 0; i < ARRAY_SIZE(key); i++)
1500c2c66affSColin Finck key[i] = lookupTable[(*lpszKey + i) & 0xFF];
1501c2c66affSColin Finck
1502c2c66affSColin Finck for (lpszKey++; *lpszKey; lpszKey++)
1503c2c66affSColin Finck {
1504c239cdd4SAmine Khaldi for (i = 0; i < ARRAY_SIZE(key); i++)
1505c2c66affSColin Finck key[i] = lookupTable[*lpszKey ^ key[i]];
1506c2c66affSColin Finck }
1507c2c66affSColin Finck
1508c2c66affSColin Finck return *(DWORD *)key;
1509c2c66affSColin Finck }
1510c2c66affSColin Finck
urlcache_get_hash_table(const urlcache_header * pHeader,DWORD dwOffset)1511c2c66affSColin Finck static inline entry_hash_table* urlcache_get_hash_table(const urlcache_header *pHeader, DWORD dwOffset)
1512c2c66affSColin Finck {
1513c2c66affSColin Finck if(!dwOffset)
1514c2c66affSColin Finck return NULL;
1515c2c66affSColin Finck return (entry_hash_table*)((LPBYTE)pHeader + dwOffset);
1516c2c66affSColin Finck }
1517c2c66affSColin Finck
urlcache_find_hash_entry(const urlcache_header * pHeader,LPCSTR lpszUrl,struct hash_entry ** ppHashEntry)1518c2c66affSColin Finck static BOOL urlcache_find_hash_entry(const urlcache_header *pHeader, LPCSTR lpszUrl, struct hash_entry **ppHashEntry)
1519c2c66affSColin Finck {
1520c2c66affSColin Finck /* structure of hash table:
1521c2c66affSColin Finck * 448 entries divided into 64 blocks
1522c2c66affSColin Finck * each block therefore contains a chain of 7 key/offset pairs
1523c2c66affSColin Finck * how position in table is calculated:
1524c2c66affSColin Finck * 1. the url is hashed in helper function
1525c2c66affSColin Finck * 2. the key % HASHTABLE_NUM_ENTRIES is the bucket number
1526c2c66affSColin Finck * 3. bucket number * HASHTABLE_BLOCKSIZE is offset of the bucket
1527c2c66affSColin Finck *
1528c2c66affSColin Finck * note:
1529c2c66affSColin Finck * there can be multiple hash tables in the file and the offset to
1530c2c66affSColin Finck * the next one is stored in the header of the hash table
1531c2c66affSColin Finck */
1532c2c66affSColin Finck DWORD key = urlcache_hash_key(lpszUrl);
1533c2c66affSColin Finck DWORD offset = (key & (HASHTABLE_NUM_ENTRIES-1)) * HASHTABLE_BLOCKSIZE;
1534c2c66affSColin Finck entry_hash_table* pHashEntry;
1535c2c66affSColin Finck DWORD id = 0;
1536c2c66affSColin Finck
1537c2c66affSColin Finck key >>= HASHTABLE_FLAG_BITS;
1538c2c66affSColin Finck
1539c2c66affSColin Finck for (pHashEntry = urlcache_get_hash_table(pHeader, pHeader->hash_table_off);
1540c2c66affSColin Finck pHashEntry; pHashEntry = urlcache_get_hash_table(pHeader, pHashEntry->next))
1541c2c66affSColin Finck {
1542c2c66affSColin Finck int i;
1543c2c66affSColin Finck if (pHashEntry->id != id++)
1544c2c66affSColin Finck {
1545c2c66affSColin Finck ERR("Error: not right hash table number (%d) expected %d\n", pHashEntry->id, id);
1546c2c66affSColin Finck continue;
1547c2c66affSColin Finck }
1548c2c66affSColin Finck /* make sure that it is in fact a hash entry */
1549c2c66affSColin Finck if (pHashEntry->header.signature != HASH_SIGNATURE)
1550c2c66affSColin Finck {
1551c2c66affSColin Finck ERR("Error: not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&pHashEntry->header.signature);
1552c2c66affSColin Finck continue;
1553c2c66affSColin Finck }
1554c2c66affSColin Finck
1555c2c66affSColin Finck for (i = 0; i < HASHTABLE_BLOCKSIZE; i++)
1556c2c66affSColin Finck {
1557c2c66affSColin Finck struct hash_entry *pHashElement = &pHashEntry->hash_table[offset + i];
1558c2c66affSColin Finck if (key == pHashElement->key>>HASHTABLE_FLAG_BITS)
1559c2c66affSColin Finck {
1560c2c66affSColin Finck /* FIXME: we should make sure that this is the right element
1561c2c66affSColin Finck * before returning and claiming that it is. We can do this
1562c2c66affSColin Finck * by doing a simple compare between the URL we were given
1563c2c66affSColin Finck * and the URL stored in the entry. However, this assumes
1564c2c66affSColin Finck * we know the format of all the entries stored in the
1565c2c66affSColin Finck * hash table */
1566c2c66affSColin Finck *ppHashEntry = pHashElement;
1567c2c66affSColin Finck return TRUE;
1568c2c66affSColin Finck }
1569c2c66affSColin Finck }
1570c2c66affSColin Finck }
1571c2c66affSColin Finck return FALSE;
1572c2c66affSColin Finck }
1573c2c66affSColin Finck
1574c2c66affSColin Finck /***********************************************************************
1575c2c66affSColin Finck * urlcache_hash_entry_set_flags (Internal)
1576c2c66affSColin Finck *
1577c2c66affSColin Finck * Sets special bits in hash key
1578c2c66affSColin Finck *
1579c2c66affSColin Finck * RETURNS
1580c2c66affSColin Finck * nothing
1581c2c66affSColin Finck *
1582c2c66affSColin Finck */
urlcache_hash_entry_set_flags(struct hash_entry * pHashEntry,DWORD dwFlag)1583c2c66affSColin Finck static void urlcache_hash_entry_set_flags(struct hash_entry *pHashEntry, DWORD dwFlag)
1584c2c66affSColin Finck {
1585c2c66affSColin Finck pHashEntry->key = (pHashEntry->key >> HASHTABLE_FLAG_BITS << HASHTABLE_FLAG_BITS) | dwFlag;
1586c2c66affSColin Finck }
1587c2c66affSColin Finck
1588c2c66affSColin Finck /***********************************************************************
1589c2c66affSColin Finck * urlcache_hash_entry_delete (Internal)
1590c2c66affSColin Finck *
1591c2c66affSColin Finck * Searches all the hash tables in the index for the given URL and
1592c2c66affSColin Finck * then if found deletes the entry.
1593c2c66affSColin Finck *
1594c2c66affSColin Finck * RETURNS
1595c2c66affSColin Finck * TRUE if the entry was found
1596c2c66affSColin Finck * FALSE if the entry could not be found
1597c2c66affSColin Finck *
1598c2c66affSColin Finck */
urlcache_hash_entry_delete(struct hash_entry * pHashEntry)1599c2c66affSColin Finck static BOOL urlcache_hash_entry_delete(struct hash_entry *pHashEntry)
1600c2c66affSColin Finck {
1601c2c66affSColin Finck pHashEntry->key = HASHTABLE_DEL;
1602c2c66affSColin Finck return TRUE;
1603c2c66affSColin Finck }
1604c2c66affSColin Finck
1605c2c66affSColin Finck /***********************************************************************
1606c2c66affSColin Finck * urlcache_hash_entry_create (Internal)
1607c2c66affSColin Finck *
1608c2c66affSColin Finck * Searches all the hash tables for a free slot based on the offset
1609c2c66affSColin Finck * generated from the hash key. If a free slot is found, the offset and
1610c2c66affSColin Finck * key are entered into the hash table.
1611c2c66affSColin Finck *
1612c2c66affSColin Finck * RETURNS
1613c2c66affSColin Finck * ERROR_SUCCESS if the entry was added
1614c2c66affSColin Finck * Any other Win32 error code if the entry could not be added
1615c2c66affSColin Finck *
1616c2c66affSColin Finck */
urlcache_hash_entry_create(urlcache_header * pHeader,LPCSTR lpszUrl,DWORD dwOffsetEntry,DWORD dwFieldType)1617c2c66affSColin Finck static DWORD urlcache_hash_entry_create(urlcache_header *pHeader, LPCSTR lpszUrl, DWORD dwOffsetEntry, DWORD dwFieldType)
1618c2c66affSColin Finck {
1619c2c66affSColin Finck /* see urlcache_find_hash_entry for structure of hash tables */
1620c2c66affSColin Finck
1621c2c66affSColin Finck DWORD key = urlcache_hash_key(lpszUrl);
1622c2c66affSColin Finck DWORD offset = (key & (HASHTABLE_NUM_ENTRIES-1)) * HASHTABLE_BLOCKSIZE;
1623c2c66affSColin Finck entry_hash_table* pHashEntry, *pHashPrev = NULL;
1624c2c66affSColin Finck DWORD id = 0;
1625c2c66affSColin Finck DWORD error;
1626c2c66affSColin Finck
1627c2c66affSColin Finck key = ((key >> HASHTABLE_FLAG_BITS) << HASHTABLE_FLAG_BITS) + dwFieldType;
1628c2c66affSColin Finck
1629c2c66affSColin Finck for (pHashEntry = urlcache_get_hash_table(pHeader, pHeader->hash_table_off);
1630c2c66affSColin Finck pHashEntry; pHashEntry = urlcache_get_hash_table(pHeader, pHashEntry->next))
1631c2c66affSColin Finck {
1632c2c66affSColin Finck int i;
1633c2c66affSColin Finck pHashPrev = pHashEntry;
1634c2c66affSColin Finck
1635c2c66affSColin Finck if (pHashEntry->id != id++)
1636c2c66affSColin Finck {
1637c2c66affSColin Finck ERR("not right hash table number (%d) expected %d\n", pHashEntry->id, id);
1638c2c66affSColin Finck break;
1639c2c66affSColin Finck }
1640c2c66affSColin Finck /* make sure that it is in fact a hash entry */
1641c2c66affSColin Finck if (pHashEntry->header.signature != HASH_SIGNATURE)
1642c2c66affSColin Finck {
1643c2c66affSColin Finck ERR("not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&pHashEntry->header.signature);
1644c2c66affSColin Finck break;
1645c2c66affSColin Finck }
1646c2c66affSColin Finck
1647c2c66affSColin Finck for (i = 0; i < HASHTABLE_BLOCKSIZE; i++)
1648c2c66affSColin Finck {
1649c2c66affSColin Finck struct hash_entry *pHashElement = &pHashEntry->hash_table[offset + i];
1650c2c66affSColin Finck if (pHashElement->key==HASHTABLE_FREE || pHashElement->key==HASHTABLE_DEL) /* if the slot is free */
1651c2c66affSColin Finck {
1652c2c66affSColin Finck pHashElement->key = key;
1653c2c66affSColin Finck pHashElement->offset = dwOffsetEntry;
1654c2c66affSColin Finck return ERROR_SUCCESS;
1655c2c66affSColin Finck }
1656c2c66affSColin Finck }
1657c2c66affSColin Finck }
1658c2c66affSColin Finck error = urlcache_create_hash_table(pHeader, pHashPrev, &pHashEntry);
1659c2c66affSColin Finck if (error != ERROR_SUCCESS)
1660c2c66affSColin Finck return error;
1661c2c66affSColin Finck
1662c2c66affSColin Finck pHashEntry->hash_table[offset].key = key;
1663c2c66affSColin Finck pHashEntry->hash_table[offset].offset = dwOffsetEntry;
1664c2c66affSColin Finck return ERROR_SUCCESS;
1665c2c66affSColin Finck }
1666c2c66affSColin Finck
1667c2c66affSColin Finck /***********************************************************************
1668c2c66affSColin Finck * urlcache_enum_hash_tables (Internal)
1669c2c66affSColin Finck *
1670c2c66affSColin Finck * Enumerates the hash tables in a container.
1671c2c66affSColin Finck *
1672c2c66affSColin Finck * RETURNS
1673c2c66affSColin Finck * TRUE if an entry was found
1674c2c66affSColin Finck * FALSE if there are no more tables to enumerate.
1675c2c66affSColin Finck *
1676c2c66affSColin Finck */
urlcache_enum_hash_tables(const urlcache_header * pHeader,DWORD * id,entry_hash_table ** ppHashEntry)1677c2c66affSColin Finck static BOOL urlcache_enum_hash_tables(const urlcache_header *pHeader, DWORD *id, entry_hash_table **ppHashEntry)
1678c2c66affSColin Finck {
1679c2c66affSColin Finck for (*ppHashEntry = urlcache_get_hash_table(pHeader, pHeader->hash_table_off);
1680c2c66affSColin Finck *ppHashEntry; *ppHashEntry = urlcache_get_hash_table(pHeader, (*ppHashEntry)->next))
1681c2c66affSColin Finck {
1682c2c66affSColin Finck TRACE("looking at hash table number %d\n", (*ppHashEntry)->id);
1683c2c66affSColin Finck if ((*ppHashEntry)->id != *id)
1684c2c66affSColin Finck continue;
1685c2c66affSColin Finck /* make sure that it is in fact a hash entry */
1686c2c66affSColin Finck if ((*ppHashEntry)->header.signature != HASH_SIGNATURE)
1687c2c66affSColin Finck {
1688c2c66affSColin Finck ERR("Error: not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&(*ppHashEntry)->header.signature);
1689c2c66affSColin Finck (*id)++;
1690c2c66affSColin Finck continue;
1691c2c66affSColin Finck }
1692c2c66affSColin Finck
1693c2c66affSColin Finck TRACE("hash table number %d found\n", *id);
1694c2c66affSColin Finck return TRUE;
1695c2c66affSColin Finck }
1696c2c66affSColin Finck return FALSE;
1697c2c66affSColin Finck }
1698c2c66affSColin Finck
1699c2c66affSColin Finck /***********************************************************************
1700c2c66affSColin Finck * urlcache_enum_hash_table_entries (Internal)
1701c2c66affSColin Finck *
1702c2c66affSColin Finck * Enumerates entries in a hash table and returns the next non-free entry.
1703c2c66affSColin Finck *
1704c2c66affSColin Finck * RETURNS
1705c2c66affSColin Finck * TRUE if an entry was found
1706c2c66affSColin Finck * FALSE if the hash table is empty or there are no more entries to
1707c2c66affSColin Finck * enumerate.
1708c2c66affSColin Finck *
1709c2c66affSColin Finck */
urlcache_enum_hash_table_entries(const urlcache_header * pHeader,const entry_hash_table * pHashEntry,DWORD * index,const struct hash_entry ** ppHashEntry)1710c2c66affSColin Finck static BOOL urlcache_enum_hash_table_entries(const urlcache_header *pHeader, const entry_hash_table *pHashEntry,
1711c2c66affSColin Finck DWORD * index, const struct hash_entry **ppHashEntry)
1712c2c66affSColin Finck {
1713c2c66affSColin Finck for (; *index < HASHTABLE_SIZE ; (*index)++)
1714c2c66affSColin Finck {
1715c2c66affSColin Finck if (pHashEntry->hash_table[*index].key==HASHTABLE_FREE || pHashEntry->hash_table[*index].key==HASHTABLE_DEL)
1716c2c66affSColin Finck continue;
1717c2c66affSColin Finck
1718c2c66affSColin Finck *ppHashEntry = &pHashEntry->hash_table[*index];
1719c2c66affSColin Finck TRACE("entry found %d\n", *index);
1720c2c66affSColin Finck return TRUE;
1721c2c66affSColin Finck }
1722c2c66affSColin Finck TRACE("no more entries (%d)\n", *index);
1723c2c66affSColin Finck return FALSE;
1724c2c66affSColin Finck }
1725c2c66affSColin Finck
1726c2c66affSColin Finck /***********************************************************************
1727c2c66affSColin Finck * cache_container_delete_dir (Internal)
1728c2c66affSColin Finck *
1729c2c66affSColin Finck * Erase a directory containing an URL cache.
1730c2c66affSColin Finck *
1731c2c66affSColin Finck * RETURNS
1732c2c66affSColin Finck * TRUE success, FALSE failure/aborted.
1733c2c66affSColin Finck *
1734c2c66affSColin Finck */
cache_container_delete_dir(LPCWSTR lpszPath)1735c2c66affSColin Finck static BOOL cache_container_delete_dir(LPCWSTR lpszPath)
1736c2c66affSColin Finck {
1737c2c66affSColin Finck DWORD path_len;
1738c2c66affSColin Finck WCHAR path[MAX_PATH + 1];
1739c2c66affSColin Finck SHFILEOPSTRUCTW shfos;
1740c2c66affSColin Finck int ret;
1741c2c66affSColin Finck
17425f12c8d7Swinesync path_len = lstrlenW(lpszPath);
1743c2c66affSColin Finck if (path_len >= MAX_PATH)
1744c2c66affSColin Finck return FALSE;
17455f12c8d7Swinesync lstrcpyW(path, lpszPath);
1746c2c66affSColin Finck path[path_len + 1] = 0; /* double-NUL-terminate path */
1747c2c66affSColin Finck
1748c2c66affSColin Finck shfos.hwnd = NULL;
1749c2c66affSColin Finck shfos.wFunc = FO_DELETE;
1750c2c66affSColin Finck shfos.pFrom = path;
1751c2c66affSColin Finck shfos.pTo = NULL;
1752c2c66affSColin Finck shfos.fFlags = FOF_NOCONFIRMATION;
1753c2c66affSColin Finck shfos.fAnyOperationsAborted = FALSE;
1754c2c66affSColin Finck ret = SHFileOperationW(&shfos);
1755c2c66affSColin Finck if (ret)
1756c2c66affSColin Finck ERR("SHFileOperationW on %s returned %i\n", debugstr_w(path), ret);
1757c2c66affSColin Finck return !(ret || shfos.fAnyOperationsAborted);
1758c2c66affSColin Finck }
1759c2c66affSColin Finck
1760c2c66affSColin Finck /***********************************************************************
1761c2c66affSColin Finck * urlcache_hash_entry_is_locked (Internal)
1762c2c66affSColin Finck *
1763c2c66affSColin Finck * Checks if entry is locked. Unlocks it if possible.
1764c2c66affSColin Finck */
urlcache_hash_entry_is_locked(struct hash_entry * hash_entry,entry_url * url_entry)1765c2c66affSColin Finck static BOOL urlcache_hash_entry_is_locked(struct hash_entry *hash_entry, entry_url *url_entry)
1766c2c66affSColin Finck {
1767c2c66affSColin Finck FILETIME cur_time;
1768c2c66affSColin Finck ULARGE_INTEGER acc_time, time;
1769c2c66affSColin Finck
1770c2c66affSColin Finck if ((hash_entry->key & ((1<<HASHTABLE_FLAG_BITS)-1)) != HASHTABLE_LOCK)
1771c2c66affSColin Finck return FALSE;
1772c2c66affSColin Finck
1773c2c66affSColin Finck GetSystemTimeAsFileTime(&cur_time);
1774c2c66affSColin Finck time.u.LowPart = cur_time.dwLowDateTime;
1775c2c66affSColin Finck time.u.HighPart = cur_time.dwHighDateTime;
1776c2c66affSColin Finck
1777c2c66affSColin Finck acc_time.u.LowPart = url_entry->access_time.dwLowDateTime;
1778c2c66affSColin Finck acc_time.u.HighPart = url_entry->access_time.dwHighDateTime;
1779c2c66affSColin Finck
1780c2c66affSColin Finck time.QuadPart -= acc_time.QuadPart;
1781c2c66affSColin Finck
1782c2c66affSColin Finck /* check if entry was locked for at least a day */
1783c2c66affSColin Finck if(time.QuadPart > (ULONGLONG)24*60*60*FILETIME_SECOND) {
1784c2c66affSColin Finck urlcache_hash_entry_set_flags(hash_entry, HASHTABLE_URL);
1785c2c66affSColin Finck url_entry->use_count = 0;
1786c2c66affSColin Finck return FALSE;
1787c2c66affSColin Finck }
1788c2c66affSColin Finck
1789c2c66affSColin Finck return TRUE;
1790c2c66affSColin Finck }
1791c2c66affSColin Finck
urlcache_get_entry_info(const char * url,void * entry_info,DWORD * size,DWORD flags,BOOL unicode)1792c2c66affSColin Finck static BOOL urlcache_get_entry_info(const char *url, void *entry_info,
1793c2c66affSColin Finck DWORD *size, DWORD flags, BOOL unicode)
1794c2c66affSColin Finck {
1795c2c66affSColin Finck urlcache_header *header;
1796c2c66affSColin Finck struct hash_entry *hash_entry;
1797c2c66affSColin Finck const entry_url *url_entry;
1798c2c66affSColin Finck cache_container *container;
1799c2c66affSColin Finck DWORD error;
1800c2c66affSColin Finck
1801c2c66affSColin Finck TRACE("(%s, %p, %p, %x, %x)\n", debugstr_a(url), entry_info, size, flags, unicode);
1802c2c66affSColin Finck
1803c2c66affSColin Finck if(flags & ~GET_INSTALLED_ENTRY)
1804c2c66affSColin Finck FIXME("ignoring unsupported flags: %x\n", flags);
1805c2c66affSColin Finck
1806c2c66affSColin Finck error = cache_containers_find(url, &container);
1807c2c66affSColin Finck if(error != ERROR_SUCCESS) {
1808c2c66affSColin Finck SetLastError(error);
1809c2c66affSColin Finck return FALSE;
1810c2c66affSColin Finck }
1811c2c66affSColin Finck
1812c2c66affSColin Finck error = cache_container_open_index(container, MIN_BLOCK_NO);
1813c2c66affSColin Finck if(error != ERROR_SUCCESS) {
1814c2c66affSColin Finck SetLastError(error);
1815c2c66affSColin Finck return FALSE;
1816c2c66affSColin Finck }
1817c2c66affSColin Finck
1818c2c66affSColin Finck if(!(header = cache_container_lock_index(container)))
1819c2c66affSColin Finck return FALSE;
1820c2c66affSColin Finck
1821c2c66affSColin Finck if(!urlcache_find_hash_entry(header, url, &hash_entry)) {
1822c2c66affSColin Finck cache_container_unlock_index(container, header);
1823c2c66affSColin Finck WARN("entry %s not found!\n", debugstr_a(url));
1824c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
1825c2c66affSColin Finck return FALSE;
1826c2c66affSColin Finck }
1827c2c66affSColin Finck
1828c2c66affSColin Finck url_entry = (const entry_url*)((LPBYTE)header + hash_entry->offset);
1829c2c66affSColin Finck if(url_entry->header.signature != URL_SIGNATURE) {
1830c2c66affSColin Finck FIXME("Trying to retrieve entry of unknown format %s\n",
1831c2c66affSColin Finck debugstr_an((LPCSTR)&url_entry->header.signature, sizeof(DWORD)));
1832ef9a828eSwinesync cache_container_unlock_index(container, header);
1833c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
1834c2c66affSColin Finck return FALSE;
1835c2c66affSColin Finck }
1836c2c66affSColin Finck
1837c2c66affSColin Finck TRACE("Found URL: %s\n", debugstr_a((LPCSTR)url_entry + url_entry->url_off));
1838c2c66affSColin Finck TRACE("Header info: %s\n", debugstr_an((LPCSTR)url_entry +
1839c2c66affSColin Finck url_entry->header_info_off, url_entry->header_info_size));
1840c2c66affSColin Finck
1841c2c66affSColin Finck if((flags & GET_INSTALLED_ENTRY) && !(url_entry->cache_entry_type & INSTALLED_CACHE_ENTRY)) {
1842c2c66affSColin Finck cache_container_unlock_index(container, header);
1843c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
1844c2c66affSColin Finck return FALSE;
1845c2c66affSColin Finck }
1846c2c66affSColin Finck
1847c2c66affSColin Finck if(size) {
1848c2c66affSColin Finck if(!entry_info)
1849c2c66affSColin Finck *size = 0;
1850c2c66affSColin Finck
1851c2c66affSColin Finck error = urlcache_copy_entry(container, header, entry_info, size, url_entry, unicode);
1852c2c66affSColin Finck if(error != ERROR_SUCCESS) {
1853c2c66affSColin Finck cache_container_unlock_index(container, header);
1854c2c66affSColin Finck SetLastError(error);
1855c2c66affSColin Finck return FALSE;
1856c2c66affSColin Finck }
1857c2c66affSColin Finck if(url_entry->local_name_off)
1858c2c66affSColin Finck TRACE("Local File Name: %s\n", debugstr_a((LPCSTR)url_entry + url_entry->local_name_off));
1859c2c66affSColin Finck }
1860c2c66affSColin Finck
1861c2c66affSColin Finck cache_container_unlock_index(container, header);
1862c2c66affSColin Finck return TRUE;
1863c2c66affSColin Finck }
1864c2c66affSColin Finck
1865c2c66affSColin Finck /***********************************************************************
1866c2c66affSColin Finck * GetUrlCacheEntryInfoExA (WININET.@)
1867c2c66affSColin Finck *
1868c2c66affSColin Finck */
GetUrlCacheEntryInfoExA(LPCSTR lpszUrl,LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,LPDWORD lpdwCacheEntryInfoBufSize,LPSTR lpszReserved,LPDWORD lpdwReserved,LPVOID lpReserved,DWORD dwFlags)1869c2c66affSColin Finck BOOL WINAPI GetUrlCacheEntryInfoExA(LPCSTR lpszUrl,
1870c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
1871c2c66affSColin Finck LPDWORD lpdwCacheEntryInfoBufSize, LPSTR lpszReserved,
1872c2c66affSColin Finck LPDWORD lpdwReserved, LPVOID lpReserved, DWORD dwFlags)
1873c2c66affSColin Finck {
1874c2c66affSColin Finck if(lpszReserved!=NULL || lpdwReserved!=NULL || lpReserved!=NULL) {
1875c2c66affSColin Finck ERR("Reserved value was not 0\n");
1876c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
1877c2c66affSColin Finck return FALSE;
1878c2c66affSColin Finck }
1879c2c66affSColin Finck
1880c2c66affSColin Finck return urlcache_get_entry_info(lpszUrl, lpCacheEntryInfo,
1881c2c66affSColin Finck lpdwCacheEntryInfoBufSize, dwFlags, FALSE);
1882c2c66affSColin Finck }
1883c2c66affSColin Finck
1884c2c66affSColin Finck /***********************************************************************
1885c2c66affSColin Finck * GetUrlCacheEntryInfoA (WININET.@)
1886c2c66affSColin Finck *
1887c2c66affSColin Finck */
GetUrlCacheEntryInfoA(LPCSTR lpszUrlName,LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,LPDWORD lpdwCacheEntryInfoBufferSize)1888c2c66affSColin Finck BOOL WINAPI GetUrlCacheEntryInfoA(LPCSTR lpszUrlName,
1889c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
1890c2c66affSColin Finck LPDWORD lpdwCacheEntryInfoBufferSize)
1891c2c66affSColin Finck {
1892c2c66affSColin Finck return GetUrlCacheEntryInfoExA(lpszUrlName, lpCacheEntryInfo,
1893c2c66affSColin Finck lpdwCacheEntryInfoBufferSize, NULL, NULL, NULL, 0);
1894c2c66affSColin Finck }
1895c2c66affSColin Finck
urlcache_encode_url(const WCHAR * url,char * encoded_url,int encoded_len)1896c2c66affSColin Finck static int urlcache_encode_url(const WCHAR *url, char *encoded_url, int encoded_len)
1897c2c66affSColin Finck {
1898c2c66affSColin Finck URL_COMPONENTSW uc;
1899c2c66affSColin Finck DWORD len, part_len;
1900c2c66affSColin Finck WCHAR *punycode;
1901c2c66affSColin Finck
1902c2c66affSColin Finck TRACE("%s\n", debugstr_w(url));
1903c2c66affSColin Finck
1904c2c66affSColin Finck memset(&uc, 0, sizeof(uc));
1905c2c66affSColin Finck uc.dwStructSize = sizeof(uc);
1906c2c66affSColin Finck uc.dwHostNameLength = 1;
1907c2c66affSColin Finck if(!InternetCrackUrlW(url, 0, 0, &uc))
1908c2c66affSColin Finck uc.nScheme = INTERNET_SCHEME_UNKNOWN;
1909c2c66affSColin Finck
1910c2c66affSColin Finck if(uc.nScheme!=INTERNET_SCHEME_HTTP && uc.nScheme!=INTERNET_SCHEME_HTTPS)
1911c2c66affSColin Finck return WideCharToMultiByte(CP_UTF8, 0, url, -1, encoded_url, encoded_len, NULL, NULL);
1912c2c66affSColin Finck
1913c2c66affSColin Finck len = WideCharToMultiByte(CP_UTF8, 0, url, uc.lpszHostName-url,
1914c2c66affSColin Finck encoded_url, encoded_len, NULL, NULL);
1915c2c66affSColin Finck if(!len)
1916c2c66affSColin Finck return 0;
1917c2c66affSColin Finck if(encoded_url)
1918c2c66affSColin Finck encoded_len -= len;
1919c2c66affSColin Finck
1920c2c66affSColin Finck part_len = IdnToAscii(0, uc.lpszHostName, uc.dwHostNameLength, NULL, 0);
1921c2c66affSColin Finck if(!part_len) {
1922c2c66affSColin Finck SetLastError(ERROR_INTERNET_INVALID_URL);
1923c2c66affSColin Finck return 0;
1924c2c66affSColin Finck }
1925c2c66affSColin Finck
1926c2c66affSColin Finck punycode = heap_alloc(part_len*sizeof(WCHAR));
1927c2c66affSColin Finck if(!punycode)
1928c2c66affSColin Finck return 0;
1929c2c66affSColin Finck
1930c2c66affSColin Finck part_len = IdnToAscii(0, uc.lpszHostName, uc.dwHostNameLength, punycode, part_len);
1931c2c66affSColin Finck if(!part_len) {
1932c2c66affSColin Finck heap_free(punycode);
1933c2c66affSColin Finck return 0;
1934c2c66affSColin Finck }
1935c2c66affSColin Finck
1936c2c66affSColin Finck part_len = WideCharToMultiByte(CP_UTF8, 0, punycode, part_len,
1937c2c66affSColin Finck encoded_url ? encoded_url+len : NULL, encoded_len, NULL, NULL);
1938c2c66affSColin Finck heap_free(punycode);
1939c2c66affSColin Finck if(!part_len)
1940c2c66affSColin Finck return 0;
1941c2c66affSColin Finck if(encoded_url)
1942c2c66affSColin Finck encoded_len -= part_len;
1943c2c66affSColin Finck len += part_len;
1944c2c66affSColin Finck
1945c2c66affSColin Finck part_len = WideCharToMultiByte(CP_UTF8, 0, uc.lpszHostName+uc.dwHostNameLength,
1946c2c66affSColin Finck -1, encoded_url ? encoded_url+len : NULL, encoded_len, NULL, NULL);
1947c2c66affSColin Finck if(!part_len)
1948c2c66affSColin Finck return 0;
1949c2c66affSColin Finck len += part_len;
1950c2c66affSColin Finck
1951c2c66affSColin Finck TRACE("got (%d)%s\n", len, debugstr_a(encoded_url));
1952c2c66affSColin Finck return len;
1953c2c66affSColin Finck }
1954c2c66affSColin Finck
urlcache_encode_url_alloc(const WCHAR * url,char ** encoded_url)1955c2c66affSColin Finck static BOOL urlcache_encode_url_alloc(const WCHAR *url, char **encoded_url)
1956c2c66affSColin Finck {
1957c2c66affSColin Finck DWORD encoded_len;
1958c2c66affSColin Finck char *ret;
1959c2c66affSColin Finck
1960c2c66affSColin Finck encoded_len = urlcache_encode_url(url, NULL, 0);
1961c2c66affSColin Finck if(!encoded_len)
1962c2c66affSColin Finck return FALSE;
1963c2c66affSColin Finck
1964c2c66affSColin Finck ret = heap_alloc(encoded_len*sizeof(WCHAR));
1965c2c66affSColin Finck if(!ret)
1966c2c66affSColin Finck return FALSE;
1967c2c66affSColin Finck
1968c2c66affSColin Finck encoded_len = urlcache_encode_url(url, ret, encoded_len);
1969c2c66affSColin Finck if(!encoded_len) {
1970c2c66affSColin Finck heap_free(ret);
1971c2c66affSColin Finck return FALSE;
1972c2c66affSColin Finck }
1973c2c66affSColin Finck
1974c2c66affSColin Finck *encoded_url = ret;
1975c2c66affSColin Finck return TRUE;
1976c2c66affSColin Finck }
1977c2c66affSColin Finck
1978c2c66affSColin Finck /***********************************************************************
1979c2c66affSColin Finck * GetUrlCacheEntryInfoExW (WININET.@)
1980c2c66affSColin Finck *
1981c2c66affSColin Finck */
GetUrlCacheEntryInfoExW(LPCWSTR lpszUrl,LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,LPDWORD lpdwCacheEntryInfoBufSize,LPWSTR lpszReserved,LPDWORD lpdwReserved,LPVOID lpReserved,DWORD dwFlags)1982c2c66affSColin Finck BOOL WINAPI GetUrlCacheEntryInfoExW(LPCWSTR lpszUrl,
1983c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
1984c2c66affSColin Finck LPDWORD lpdwCacheEntryInfoBufSize, LPWSTR lpszReserved,
1985c2c66affSColin Finck LPDWORD lpdwReserved, LPVOID lpReserved, DWORD dwFlags)
1986c2c66affSColin Finck {
1987c2c66affSColin Finck char *url;
1988c2c66affSColin Finck BOOL ret;
1989c2c66affSColin Finck
1990c2c66affSColin Finck if(lpszReserved!=NULL || lpdwReserved!=NULL || lpReserved!=NULL) {
1991c2c66affSColin Finck ERR("Reserved value was not 0\n");
1992c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
1993c2c66affSColin Finck return FALSE;
1994c2c66affSColin Finck }
1995c2c66affSColin Finck
1996c2c66affSColin Finck /* Ignore GET_INSTALLED_ENTRY flag in unicode version of function */
1997c2c66affSColin Finck dwFlags &= ~GET_INSTALLED_ENTRY;
1998c2c66affSColin Finck
1999c2c66affSColin Finck if(!urlcache_encode_url_alloc(lpszUrl, &url))
2000c2c66affSColin Finck return FALSE;
2001c2c66affSColin Finck
2002c2c66affSColin Finck ret = urlcache_get_entry_info(url, lpCacheEntryInfo,
2003c2c66affSColin Finck lpdwCacheEntryInfoBufSize, dwFlags, TRUE);
2004c2c66affSColin Finck heap_free(url);
2005c2c66affSColin Finck return ret;
2006c2c66affSColin Finck }
2007c2c66affSColin Finck
2008c2c66affSColin Finck /***********************************************************************
2009c2c66affSColin Finck * GetUrlCacheEntryInfoW (WININET.@)
2010c2c66affSColin Finck *
2011c2c66affSColin Finck */
GetUrlCacheEntryInfoW(LPCWSTR lpszUrl,LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,LPDWORD lpdwCacheEntryInfoBufferSize)2012c2c66affSColin Finck BOOL WINAPI GetUrlCacheEntryInfoW(LPCWSTR lpszUrl,
2013c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
2014c2c66affSColin Finck LPDWORD lpdwCacheEntryInfoBufferSize)
2015c2c66affSColin Finck {
2016c2c66affSColin Finck return GetUrlCacheEntryInfoExW(lpszUrl, lpCacheEntryInfo,
2017c2c66affSColin Finck lpdwCacheEntryInfoBufferSize, NULL, NULL, NULL, 0);
2018c2c66affSColin Finck }
2019c2c66affSColin Finck
2020c2c66affSColin Finck /***********************************************************************
2021c2c66affSColin Finck * SetUrlCacheEntryInfoA (WININET.@)
2022c2c66affSColin Finck */
SetUrlCacheEntryInfoA(LPCSTR lpszUrlName,LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,DWORD dwFieldControl)2023c2c66affSColin Finck BOOL WINAPI SetUrlCacheEntryInfoA(LPCSTR lpszUrlName,
2024c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
2025c2c66affSColin Finck DWORD dwFieldControl)
2026c2c66affSColin Finck {
2027c2c66affSColin Finck urlcache_header *pHeader;
2028c2c66affSColin Finck struct hash_entry *pHashEntry;
2029c2c66affSColin Finck entry_header *pEntry;
2030c2c66affSColin Finck cache_container *pContainer;
2031c2c66affSColin Finck DWORD error;
2032c2c66affSColin Finck
2033c2c66affSColin Finck TRACE("(%s, %p, 0x%08x)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo, dwFieldControl);
2034c2c66affSColin Finck
2035c2c66affSColin Finck error = cache_containers_find(lpszUrlName, &pContainer);
2036c2c66affSColin Finck if (error != ERROR_SUCCESS)
2037c2c66affSColin Finck {
2038c2c66affSColin Finck SetLastError(error);
2039c2c66affSColin Finck return FALSE;
2040c2c66affSColin Finck }
2041c2c66affSColin Finck
2042c2c66affSColin Finck error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
2043c2c66affSColin Finck if (error != ERROR_SUCCESS)
2044c2c66affSColin Finck {
2045c2c66affSColin Finck SetLastError(error);
2046c2c66affSColin Finck return FALSE;
2047c2c66affSColin Finck }
2048c2c66affSColin Finck
2049c2c66affSColin Finck if (!(pHeader = cache_container_lock_index(pContainer)))
2050c2c66affSColin Finck return FALSE;
2051c2c66affSColin Finck
2052c2c66affSColin Finck if (!urlcache_find_hash_entry(pHeader, lpszUrlName, &pHashEntry))
2053c2c66affSColin Finck {
2054c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
2055c2c66affSColin Finck WARN("entry %s not found!\n", debugstr_a(lpszUrlName));
2056c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
2057c2c66affSColin Finck return FALSE;
2058c2c66affSColin Finck }
2059c2c66affSColin Finck
2060c2c66affSColin Finck pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->offset);
2061c2c66affSColin Finck if (pEntry->signature != URL_SIGNATURE)
2062c2c66affSColin Finck {
2063c2c66affSColin Finck FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->signature, sizeof(DWORD)));
2064ef9a828eSwinesync cache_container_unlock_index(pContainer, pHeader);
2065c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
2066c2c66affSColin Finck return FALSE;
2067c2c66affSColin Finck }
2068c2c66affSColin Finck
2069c2c66affSColin Finck urlcache_set_entry_info((entry_url*)pEntry, lpCacheEntryInfo, dwFieldControl);
2070c2c66affSColin Finck
2071c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
2072c2c66affSColin Finck
2073c2c66affSColin Finck return TRUE;
2074c2c66affSColin Finck }
2075c2c66affSColin Finck
2076c2c66affSColin Finck /***********************************************************************
2077c2c66affSColin Finck * SetUrlCacheEntryInfoW (WININET.@)
2078c2c66affSColin Finck */
SetUrlCacheEntryInfoW(LPCWSTR lpszUrl,LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,DWORD dwFieldControl)2079c2c66affSColin Finck BOOL WINAPI SetUrlCacheEntryInfoW(LPCWSTR lpszUrl,
2080c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
2081c2c66affSColin Finck DWORD dwFieldControl)
2082c2c66affSColin Finck {
2083c2c66affSColin Finck char *url;
2084c2c66affSColin Finck BOOL ret;
2085c2c66affSColin Finck
2086c2c66affSColin Finck if(!urlcache_encode_url_alloc(lpszUrl, &url))
2087c2c66affSColin Finck return FALSE;
2088c2c66affSColin Finck
2089c2c66affSColin Finck ret = SetUrlCacheEntryInfoA(url, (INTERNET_CACHE_ENTRY_INFOA*)lpCacheEntryInfo, dwFieldControl);
2090c2c66affSColin Finck heap_free(url);
2091c2c66affSColin Finck return ret;
2092c2c66affSColin Finck }
2093c2c66affSColin Finck
urlcache_entry_get_file(const char * url,void * entry_info,DWORD * size,BOOL unicode)2094c2c66affSColin Finck static BOOL urlcache_entry_get_file(const char *url, void *entry_info, DWORD *size, BOOL unicode)
2095c2c66affSColin Finck {
2096c2c66affSColin Finck urlcache_header *header;
2097c2c66affSColin Finck struct hash_entry *hash_entry;
2098c2c66affSColin Finck entry_url *url_entry;
2099c2c66affSColin Finck cache_container *container;
2100c2c66affSColin Finck DWORD error;
2101c2c66affSColin Finck
2102c2c66affSColin Finck TRACE("(%s, %p, %p, %x)\n", debugstr_a(url), entry_info, size, unicode);
2103c2c66affSColin Finck
2104c2c66affSColin Finck if(!url || !size || (!entry_info && *size)) {
2105c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
2106c2c66affSColin Finck return FALSE;
2107c2c66affSColin Finck }
2108c2c66affSColin Finck
2109c2c66affSColin Finck error = cache_containers_find(url, &container);
2110c2c66affSColin Finck if(error != ERROR_SUCCESS) {
2111c2c66affSColin Finck SetLastError(error);
2112c2c66affSColin Finck return FALSE;
2113c2c66affSColin Finck }
2114c2c66affSColin Finck
2115c2c66affSColin Finck error = cache_container_open_index(container, MIN_BLOCK_NO);
2116c2c66affSColin Finck if (error != ERROR_SUCCESS) {
2117c2c66affSColin Finck SetLastError(error);
2118c2c66affSColin Finck return FALSE;
2119c2c66affSColin Finck }
2120c2c66affSColin Finck
2121c2c66affSColin Finck if (!(header = cache_container_lock_index(container)))
2122c2c66affSColin Finck return FALSE;
2123c2c66affSColin Finck
2124c2c66affSColin Finck if (!urlcache_find_hash_entry(header, url, &hash_entry)) {
2125c2c66affSColin Finck cache_container_unlock_index(container, header);
2126c2c66affSColin Finck TRACE("entry %s not found!\n", debugstr_a(url));
2127c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
2128c2c66affSColin Finck return FALSE;
2129c2c66affSColin Finck }
2130c2c66affSColin Finck
2131c2c66affSColin Finck url_entry = (entry_url*)((LPBYTE)header + hash_entry->offset);
2132c2c66affSColin Finck if(url_entry->header.signature != URL_SIGNATURE) {
2133c2c66affSColin Finck FIXME("Trying to retrieve entry of unknown format %s\n",
2134c2c66affSColin Finck debugstr_an((LPSTR)&url_entry->header.signature, sizeof(DWORD)));
2135ef9a828eSwinesync cache_container_unlock_index(container, header);
2136c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
2137c2c66affSColin Finck return FALSE;
2138c2c66affSColin Finck }
2139c2c66affSColin Finck
2140c2c66affSColin Finck if(!url_entry->local_name_off) {
2141c2c66affSColin Finck cache_container_unlock_index(container, header);
2142c2c66affSColin Finck SetLastError(ERROR_INVALID_DATA);
2143c2c66affSColin Finck return FALSE;
2144c2c66affSColin Finck }
2145c2c66affSColin Finck
2146c2c66affSColin Finck TRACE("Found URL: %s\n", debugstr_a((LPCSTR)url_entry + url_entry->url_off));
2147c2c66affSColin Finck TRACE("Header info: %s\n", debugstr_an((LPCSTR)url_entry + url_entry->header_info_off,
2148c2c66affSColin Finck url_entry->header_info_size));
2149c2c66affSColin Finck
2150c2c66affSColin Finck error = urlcache_copy_entry(container, header, entry_info,
2151c2c66affSColin Finck size, url_entry, unicode);
2152c2c66affSColin Finck if(error != ERROR_SUCCESS) {
2153c2c66affSColin Finck cache_container_unlock_index(container, header);
2154c2c66affSColin Finck SetLastError(error);
2155c2c66affSColin Finck return FALSE;
2156c2c66affSColin Finck }
2157c2c66affSColin Finck TRACE("Local File Name: %s\n", debugstr_a((LPCSTR)url_entry + url_entry->local_name_off));
2158c2c66affSColin Finck
2159c2c66affSColin Finck url_entry->hit_rate++;
2160c2c66affSColin Finck url_entry->use_count++;
2161c2c66affSColin Finck urlcache_hash_entry_set_flags(hash_entry, HASHTABLE_LOCK);
2162c2c66affSColin Finck GetSystemTimeAsFileTime(&url_entry->access_time);
2163c2c66affSColin Finck
2164c2c66affSColin Finck cache_container_unlock_index(container, header);
2165c2c66affSColin Finck
2166c2c66affSColin Finck return TRUE;
2167c2c66affSColin Finck }
2168c2c66affSColin Finck
2169c2c66affSColin Finck /***********************************************************************
2170c2c66affSColin Finck * RetrieveUrlCacheEntryFileA (WININET.@)
2171c2c66affSColin Finck *
2172c2c66affSColin Finck */
RetrieveUrlCacheEntryFileA(LPCSTR lpszUrlName,LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,LPDWORD lpdwCacheEntryInfoBufferSize,DWORD dwReserved)2173c2c66affSColin Finck BOOL WINAPI RetrieveUrlCacheEntryFileA(LPCSTR lpszUrlName,
2174c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
2175c2c66affSColin Finck LPDWORD lpdwCacheEntryInfoBufferSize, DWORD dwReserved)
2176c2c66affSColin Finck {
2177c2c66affSColin Finck return urlcache_entry_get_file(lpszUrlName, lpCacheEntryInfo,
2178c2c66affSColin Finck lpdwCacheEntryInfoBufferSize, FALSE);
2179c2c66affSColin Finck }
2180c2c66affSColin Finck
2181c2c66affSColin Finck /***********************************************************************
2182c2c66affSColin Finck * RetrieveUrlCacheEntryFileW (WININET.@)
2183c2c66affSColin Finck *
2184c2c66affSColin Finck */
RetrieveUrlCacheEntryFileW(LPCWSTR lpszUrlName,LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,LPDWORD lpdwCacheEntryInfoBufferSize,DWORD dwReserved)2185c2c66affSColin Finck BOOL WINAPI RetrieveUrlCacheEntryFileW(LPCWSTR lpszUrlName,
2186c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
2187c2c66affSColin Finck LPDWORD lpdwCacheEntryInfoBufferSize, DWORD dwReserved)
2188c2c66affSColin Finck {
2189c2c66affSColin Finck char *url;
2190c2c66affSColin Finck BOOL ret;
2191c2c66affSColin Finck
2192c2c66affSColin Finck if(!urlcache_encode_url_alloc(lpszUrlName, &url))
2193c2c66affSColin Finck return FALSE;
2194c2c66affSColin Finck
2195c2c66affSColin Finck ret = urlcache_entry_get_file(url, lpCacheEntryInfo,
2196c2c66affSColin Finck lpdwCacheEntryInfoBufferSize, TRUE);
2197c2c66affSColin Finck heap_free(url);
2198c2c66affSColin Finck return ret;
2199c2c66affSColin Finck }
2200c2c66affSColin Finck
urlcache_entry_delete(const cache_container * pContainer,urlcache_header * pHeader,struct hash_entry * pHashEntry)2201c2c66affSColin Finck static BOOL urlcache_entry_delete(const cache_container *pContainer,
2202c2c66affSColin Finck urlcache_header *pHeader, struct hash_entry *pHashEntry)
2203c2c66affSColin Finck {
2204c2c66affSColin Finck entry_header *pEntry;
2205c2c66affSColin Finck entry_url * pUrlEntry;
2206c2c66affSColin Finck
2207c2c66affSColin Finck pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->offset);
2208c2c66affSColin Finck if (pEntry->signature != URL_SIGNATURE)
2209c2c66affSColin Finck {
2210c2c66affSColin Finck FIXME("Trying to delete entry of unknown format %s\n",
2211c2c66affSColin Finck debugstr_an((LPCSTR)&pEntry->signature, sizeof(DWORD)));
2212c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
2213c2c66affSColin Finck return FALSE;
2214c2c66affSColin Finck }
2215c2c66affSColin Finck
2216c2c66affSColin Finck pUrlEntry = (entry_url *)pEntry;
2217c2c66affSColin Finck if(urlcache_hash_entry_is_locked(pHashEntry, pUrlEntry))
2218c2c66affSColin Finck {
2219c2c66affSColin Finck TRACE("Trying to delete locked entry\n");
2220c2c66affSColin Finck pUrlEntry->cache_entry_type |= PENDING_DELETE_CACHE_ENTRY;
2221c2c66affSColin Finck SetLastError(ERROR_SHARING_VIOLATION);
2222c2c66affSColin Finck return FALSE;
2223c2c66affSColin Finck }
2224c2c66affSColin Finck
2225c2c66affSColin Finck if(!urlcache_delete_file(pContainer, pHeader, pUrlEntry))
2226c2c66affSColin Finck {
2227c2c66affSColin Finck urlcache_entry_free(pHeader, pEntry);
2228c2c66affSColin Finck }
2229c2c66affSColin Finck else
2230c2c66affSColin Finck {
2231c2c66affSColin Finck /* Add entry to leaked files list */
2232c2c66affSColin Finck pUrlEntry->header.signature = LEAK_SIGNATURE;
2233c2c66affSColin Finck pUrlEntry->exempt_delta = pHeader->options[CACHE_HEADER_DATA_ROOT_LEAK_OFFSET];
2234c2c66affSColin Finck pHeader->options[CACHE_HEADER_DATA_ROOT_LEAK_OFFSET] = pHashEntry->offset;
2235c2c66affSColin Finck }
2236c2c66affSColin Finck
2237c2c66affSColin Finck urlcache_hash_entry_delete(pHashEntry);
2238c2c66affSColin Finck return TRUE;
2239c2c66affSColin Finck }
2240c2c66affSColin Finck
2241c2c66affSColin Finck static HANDLE free_cache_running;
2242c2c66affSColin Finck static HANDLE dll_unload_event;
handle_full_cache_worker(void * param)2243c2c66affSColin Finck static DWORD WINAPI handle_full_cache_worker(void *param)
2244c2c66affSColin Finck {
2245c2c66affSColin Finck FreeUrlCacheSpaceW(NULL, 20, 0);
2246c2c66affSColin Finck ReleaseSemaphore(free_cache_running, 1, NULL);
2247c2c66affSColin Finck return 0;
2248c2c66affSColin Finck }
2249c2c66affSColin Finck
handle_full_cache(void)2250c2c66affSColin Finck static void handle_full_cache(void)
2251c2c66affSColin Finck {
2252c2c66affSColin Finck if(WaitForSingleObject(free_cache_running, 0) == WAIT_OBJECT_0) {
2253c2c66affSColin Finck if(!QueueUserWorkItem(handle_full_cache_worker, NULL, 0))
2254c2c66affSColin Finck ReleaseSemaphore(free_cache_running, 1, NULL);
2255c2c66affSColin Finck }
2256c2c66affSColin Finck }
2257c2c66affSColin Finck
2258c2c66affSColin Finck /* Enumerates entries in cache, allows cache unlocking between calls. */
urlcache_next_entry(urlcache_header * header,DWORD * hash_table_off,DWORD * hash_table_entry,struct hash_entry ** hash_entry,entry_header ** entry)2259c2c66affSColin Finck static BOOL urlcache_next_entry(urlcache_header *header, DWORD *hash_table_off, DWORD *hash_table_entry,
2260c2c66affSColin Finck struct hash_entry **hash_entry, entry_header **entry)
2261c2c66affSColin Finck {
2262c2c66affSColin Finck entry_hash_table *hashtable_entry;
2263c2c66affSColin Finck
2264c2c66affSColin Finck *hash_entry = NULL;
2265c2c66affSColin Finck *entry = NULL;
2266c2c66affSColin Finck
2267c2c66affSColin Finck if(!*hash_table_off) {
2268c2c66affSColin Finck *hash_table_off = header->hash_table_off;
2269c2c66affSColin Finck *hash_table_entry = 0;
2270c2c66affSColin Finck
2271c2c66affSColin Finck hashtable_entry = urlcache_get_hash_table(header, *hash_table_off);
2272c2c66affSColin Finck }else {
2273c2c66affSColin Finck if(*hash_table_off >= header->size) {
2274c2c66affSColin Finck *hash_table_off = 0;
2275c2c66affSColin Finck return FALSE;
2276c2c66affSColin Finck }
2277c2c66affSColin Finck
2278c2c66affSColin Finck hashtable_entry = urlcache_get_hash_table(header, *hash_table_off);
2279c2c66affSColin Finck }
2280c2c66affSColin Finck
2281c2c66affSColin Finck if(hashtable_entry->header.signature != HASH_SIGNATURE) {
2282c2c66affSColin Finck *hash_table_off = 0;
2283c2c66affSColin Finck return FALSE;
2284c2c66affSColin Finck }
2285c2c66affSColin Finck
2286c2c66affSColin Finck while(1) {
2287c2c66affSColin Finck if(*hash_table_entry >= HASHTABLE_SIZE) {
2288c2c66affSColin Finck *hash_table_off = hashtable_entry->next;
2289c2c66affSColin Finck if(!*hash_table_off) {
2290c2c66affSColin Finck *hash_table_off = 0;
2291c2c66affSColin Finck return FALSE;
2292c2c66affSColin Finck }
2293c2c66affSColin Finck
2294c2c66affSColin Finck hashtable_entry = urlcache_get_hash_table(header, *hash_table_off);
2295c2c66affSColin Finck *hash_table_entry = 0;
2296c2c66affSColin Finck }
2297c2c66affSColin Finck
2298c2c66affSColin Finck if(hashtable_entry->hash_table[*hash_table_entry].key != HASHTABLE_DEL &&
2299c2c66affSColin Finck hashtable_entry->hash_table[*hash_table_entry].key != HASHTABLE_FREE) {
2300c2c66affSColin Finck *hash_entry = &hashtable_entry->hash_table[*hash_table_entry];
2301c2c66affSColin Finck *entry = (entry_header*)((LPBYTE)header + hashtable_entry->hash_table[*hash_table_entry].offset);
2302c2c66affSColin Finck (*hash_table_entry)++;
2303c2c66affSColin Finck return TRUE;
2304c2c66affSColin Finck }
2305c2c66affSColin Finck
2306c2c66affSColin Finck (*hash_table_entry)++;
2307c2c66affSColin Finck }
2308c2c66affSColin Finck
2309c2c66affSColin Finck *hash_table_off = 0;
2310c2c66affSColin Finck return FALSE;
2311c2c66affSColin Finck }
2312c2c66affSColin Finck
2313c2c66affSColin Finck /* Rates an urlcache entry to determine if it can be deleted.
2314c2c66affSColin Finck *
2315c2c66affSColin Finck * Score 0 means that entry can safely be removed, the bigger rating
2316c2c66affSColin Finck * the smaller chance of entry being removed.
2317c2c66affSColin Finck * DWORD_MAX means that entry can't be deleted at all.
2318c2c66affSColin Finck *
2319c2c66affSColin Finck * Rating system is currently not fully compatible with native implementation.
2320c2c66affSColin Finck */
urlcache_rate_entry(entry_url * url_entry,FILETIME * cur_time)2321c2c66affSColin Finck static DWORD urlcache_rate_entry(entry_url *url_entry, FILETIME *cur_time)
2322c2c66affSColin Finck {
2323c2c66affSColin Finck ULARGE_INTEGER time, access_time;
2324c2c66affSColin Finck DWORD rating;
2325c2c66affSColin Finck
2326c2c66affSColin Finck access_time.u.LowPart = url_entry->access_time.dwLowDateTime;
2327c2c66affSColin Finck access_time.u.HighPart = url_entry->access_time.dwHighDateTime;
2328c2c66affSColin Finck
2329c2c66affSColin Finck time.u.LowPart = cur_time->dwLowDateTime;
2330c2c66affSColin Finck time.u.HighPart = cur_time->dwHighDateTime;
2331c2c66affSColin Finck
2332c2c66affSColin Finck /* Don't touch entries that were added less than 10 minutes ago */
2333c2c66affSColin Finck if(time.QuadPart < access_time.QuadPart + (ULONGLONG)10*60*FILETIME_SECOND)
2334c2c66affSColin Finck return -1;
2335c2c66affSColin Finck
2336c2c66affSColin Finck if(url_entry->cache_entry_type & STICKY_CACHE_ENTRY)
2337c2c66affSColin Finck if(time.QuadPart < access_time.QuadPart + (ULONGLONG)url_entry->exempt_delta*FILETIME_SECOND)
2338c2c66affSColin Finck return -1;
2339c2c66affSColin Finck
2340c2c66affSColin Finck time.QuadPart = (time.QuadPart-access_time.QuadPart)/FILETIME_SECOND;
2341c2c66affSColin Finck rating = 400*60*60*24/(60*60*24+time.QuadPart);
2342c2c66affSColin Finck
2343c2c66affSColin Finck if(url_entry->hit_rate > 100)
2344c2c66affSColin Finck rating += 100;
2345c2c66affSColin Finck else
2346c2c66affSColin Finck rating += url_entry->hit_rate;
2347c2c66affSColin Finck
2348c2c66affSColin Finck return rating;
2349c2c66affSColin Finck }
2350c2c66affSColin Finck
dword_cmp(const void * p1,const void * p2)23515f12c8d7Swinesync static int __cdecl dword_cmp(const void *p1, const void *p2)
2352c2c66affSColin Finck {
2353c2c66affSColin Finck return *(const DWORD*)p1 - *(const DWORD*)p2;
2354c2c66affSColin Finck }
2355c2c66affSColin Finck
2356c2c66affSColin Finck /***********************************************************************
2357c2c66affSColin Finck * FreeUrlCacheSpaceW (WININET.@)
2358c2c66affSColin Finck *
2359c2c66affSColin Finck * Frees up some cache.
2360c2c66affSColin Finck *
2361c2c66affSColin Finck * PARAMETERS
2362c2c66affSColin Finck * cache_path [I] Which volume to free up from, or NULL if you don't care.
2363c2c66affSColin Finck * size [I] Percentage of the cache that should be free.
2364c2c66affSColin Finck * filter [I] Which entries can't be deleted (CacheEntryType)
2365c2c66affSColin Finck *
2366c2c66affSColin Finck * RETURNS
2367c2c66affSColin Finck * TRUE success. FALSE failure.
2368c2c66affSColin Finck *
2369c2c66affSColin Finck * IMPLEMENTATION
2370c2c66affSColin Finck * This implementation just retrieves the path of the cache directory, and
2371c2c66affSColin Finck * deletes its contents from the filesystem. The correct approach would
2372c2c66affSColin Finck * probably be to implement and use {FindFirst,FindNext,Delete}UrlCacheGroup().
2373c2c66affSColin Finck */
FreeUrlCacheSpaceW(LPCWSTR cache_path,DWORD size,DWORD filter)2374c2c66affSColin Finck BOOL WINAPI FreeUrlCacheSpaceW(LPCWSTR cache_path, DWORD size, DWORD filter)
2375c2c66affSColin Finck {
2376c2c66affSColin Finck cache_container *container;
2377c2c66affSColin Finck DWORD path_len, err;
2378c2c66affSColin Finck
2379c2c66affSColin Finck TRACE("(%s, %x, %x)\n", debugstr_w(cache_path), size, filter);
2380c2c66affSColin Finck
2381c2c66affSColin Finck if(size<1 || size>100) {
2382c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
2383c2c66affSColin Finck return FALSE;
2384c2c66affSColin Finck }
2385c2c66affSColin Finck
2386c2c66affSColin Finck if(cache_path) {
23875f12c8d7Swinesync path_len = lstrlenW(cache_path);
2388c2c66affSColin Finck if(cache_path[path_len-1] == '\\')
2389c2c66affSColin Finck path_len--;
2390c2c66affSColin Finck }else {
2391c2c66affSColin Finck path_len = 0;
2392c2c66affSColin Finck }
2393c2c66affSColin Finck
2394c2c66affSColin Finck if(size==100 && !filter) {
2395c2c66affSColin Finck LIST_FOR_EACH_ENTRY(container, &UrlContainers, cache_container, entry)
2396c2c66affSColin Finck {
2397c2c66affSColin Finck /* When cache_path==NULL only clean Temporary Internet Files */
2398c2c66affSColin Finck if((!path_len && container->cache_prefix[0]==0) ||
23995f12c8d7Swinesync (path_len && !wcsnicmp(container->path, cache_path, path_len) &&
2400c2c66affSColin Finck (container->path[path_len]=='\0' || container->path[path_len]=='\\')))
2401c2c66affSColin Finck {
2402c2c66affSColin Finck BOOL ret_del;
2403c2c66affSColin Finck
2404c2c66affSColin Finck WaitForSingleObject(container->mutex, INFINITE);
2405c2c66affSColin Finck
2406c2c66affSColin Finck /* unlock, delete, recreate and lock cache */
2407c2c66affSColin Finck cache_container_close_index(container);
2408c2c66affSColin Finck ret_del = cache_container_delete_dir(container->path);
2409c2c66affSColin Finck err = cache_container_open_index(container, MIN_BLOCK_NO);
2410c2c66affSColin Finck
2411c2c66affSColin Finck ReleaseMutex(container->mutex);
2412c2c66affSColin Finck if(!ret_del || (err != ERROR_SUCCESS))
2413c2c66affSColin Finck return FALSE;
2414c2c66affSColin Finck }
2415c2c66affSColin Finck }
2416c2c66affSColin Finck
2417c2c66affSColin Finck return TRUE;
2418c2c66affSColin Finck }
2419c2c66affSColin Finck
2420c2c66affSColin Finck LIST_FOR_EACH_ENTRY(container, &UrlContainers, cache_container, entry)
2421c2c66affSColin Finck {
2422c2c66affSColin Finck urlcache_header *header;
2423c2c66affSColin Finck struct hash_entry *hash_entry;
2424c2c66affSColin Finck entry_header *entry;
2425c2c66affSColin Finck entry_url *url_entry;
2426c2c66affSColin Finck ULONGLONG desired_size, cur_size;
2427c2c66affSColin Finck DWORD delete_factor, hash_table_off, hash_table_entry;
2428c2c66affSColin Finck DWORD rate[100], rate_no;
2429c2c66affSColin Finck FILETIME cur_time;
2430c2c66affSColin Finck
2431c2c66affSColin Finck if((path_len || container->cache_prefix[0]!=0) &&
24325f12c8d7Swinesync (!path_len || wcsnicmp(container->path, cache_path, path_len) ||
2433c2c66affSColin Finck (container->path[path_len]!='\0' && container->path[path_len]!='\\')))
2434c2c66affSColin Finck continue;
2435c2c66affSColin Finck
2436c2c66affSColin Finck err = cache_container_open_index(container, MIN_BLOCK_NO);
2437c2c66affSColin Finck if(err != ERROR_SUCCESS)
2438c2c66affSColin Finck continue;
2439c2c66affSColin Finck
2440c2c66affSColin Finck header = cache_container_lock_index(container);
2441c2c66affSColin Finck if(!header)
2442c2c66affSColin Finck continue;
2443c2c66affSColin Finck
2444c2c66affSColin Finck urlcache_clean_leaked_entries(container, header);
2445c2c66affSColin Finck
2446c2c66affSColin Finck desired_size = header->cache_limit.QuadPart*(100-size)/100;
2447c2c66affSColin Finck cur_size = header->cache_usage.QuadPart+header->exempt_usage.QuadPart;
2448c2c66affSColin Finck if(cur_size <= desired_size)
2449c2c66affSColin Finck delete_factor = 0;
2450c2c66affSColin Finck else
2451c2c66affSColin Finck delete_factor = (cur_size-desired_size)*100/cur_size;
2452c2c66affSColin Finck
2453c2c66affSColin Finck if(!delete_factor) {
2454c2c66affSColin Finck cache_container_unlock_index(container, header);
2455c2c66affSColin Finck continue;
2456c2c66affSColin Finck }
2457c2c66affSColin Finck
2458c2c66affSColin Finck hash_table_off = 0;
2459c2c66affSColin Finck hash_table_entry = 0;
2460c2c66affSColin Finck rate_no = 0;
2461c2c66affSColin Finck GetSystemTimeAsFileTime(&cur_time);
2462c239cdd4SAmine Khaldi while(rate_no < ARRAY_SIZE(rate) &&
2463c2c66affSColin Finck urlcache_next_entry(header, &hash_table_off, &hash_table_entry, &hash_entry, &entry)) {
2464c2c66affSColin Finck if(entry->signature != URL_SIGNATURE) {
2465c2c66affSColin Finck WARN("only url entries are currently supported\n");
2466c2c66affSColin Finck continue;
2467c2c66affSColin Finck }
2468c2c66affSColin Finck
2469c2c66affSColin Finck url_entry = (entry_url*)entry;
2470c2c66affSColin Finck if(url_entry->cache_entry_type & filter)
2471c2c66affSColin Finck continue;
2472c2c66affSColin Finck
2473c2c66affSColin Finck rate[rate_no] = urlcache_rate_entry(url_entry, &cur_time);
2474c2c66affSColin Finck if(rate[rate_no] != -1)
2475c2c66affSColin Finck rate_no++;
2476c2c66affSColin Finck }
2477c2c66affSColin Finck
2478c2c66affSColin Finck if(!rate_no) {
2479c2c66affSColin Finck TRACE("nothing to delete\n");
2480c2c66affSColin Finck cache_container_unlock_index(container, header);
2481c2c66affSColin Finck continue;
2482c2c66affSColin Finck }
2483c2c66affSColin Finck
2484c2c66affSColin Finck qsort(rate, rate_no, sizeof(DWORD), dword_cmp);
2485c2c66affSColin Finck
2486c2c66affSColin Finck delete_factor = delete_factor*rate_no/100;
2487c2c66affSColin Finck delete_factor = rate[delete_factor];
2488c2c66affSColin Finck TRACE("deleting files with rating %d or less\n", delete_factor);
2489c2c66affSColin Finck
2490c2c66affSColin Finck hash_table_off = 0;
2491c2c66affSColin Finck while(urlcache_next_entry(header, &hash_table_off, &hash_table_entry, &hash_entry, &entry)) {
2492c2c66affSColin Finck if(entry->signature != URL_SIGNATURE)
2493c2c66affSColin Finck continue;
2494c2c66affSColin Finck
2495c2c66affSColin Finck url_entry = (entry_url*)entry;
2496c2c66affSColin Finck if(url_entry->cache_entry_type & filter)
2497c2c66affSColin Finck continue;
2498c2c66affSColin Finck
2499c2c66affSColin Finck if(urlcache_rate_entry(url_entry, &cur_time) <= delete_factor) {
2500c2c66affSColin Finck TRACE("deleting file: %s\n", debugstr_a((char*)url_entry+url_entry->local_name_off));
2501c2c66affSColin Finck urlcache_entry_delete(container, header, hash_entry);
2502c2c66affSColin Finck
2503c2c66affSColin Finck if(header->cache_usage.QuadPart+header->exempt_usage.QuadPart <= desired_size)
2504c2c66affSColin Finck break;
2505c2c66affSColin Finck
2506c2c66affSColin Finck /* Allow other threads to use cache while cleaning */
2507c2c66affSColin Finck cache_container_unlock_index(container, header);
2508c2c66affSColin Finck if(WaitForSingleObject(dll_unload_event, 0) == WAIT_OBJECT_0) {
2509c2c66affSColin Finck TRACE("got dll_unload_event - finishing\n");
2510c2c66affSColin Finck return TRUE;
2511c2c66affSColin Finck }
2512c2c66affSColin Finck Sleep(0);
2513c2c66affSColin Finck header = cache_container_lock_index(container);
2514c2c66affSColin Finck }
2515c2c66affSColin Finck }
2516c2c66affSColin Finck
2517c2c66affSColin Finck TRACE("cache size after cleaning 0x%s/0x%s\n",
2518c2c66affSColin Finck wine_dbgstr_longlong(header->cache_usage.QuadPart+header->exempt_usage.QuadPart),
2519c2c66affSColin Finck wine_dbgstr_longlong(header->cache_limit.QuadPart));
2520c2c66affSColin Finck cache_container_unlock_index(container, header);
2521c2c66affSColin Finck }
2522c2c66affSColin Finck
2523c2c66affSColin Finck return TRUE;
2524c2c66affSColin Finck }
2525c2c66affSColin Finck
2526c2c66affSColin Finck /***********************************************************************
2527c2c66affSColin Finck * FreeUrlCacheSpaceA (WININET.@)
2528c2c66affSColin Finck *
2529c2c66affSColin Finck * See FreeUrlCacheSpaceW.
2530c2c66affSColin Finck */
FreeUrlCacheSpaceA(LPCSTR lpszCachePath,DWORD dwSize,DWORD dwFilter)2531c2c66affSColin Finck BOOL WINAPI FreeUrlCacheSpaceA(LPCSTR lpszCachePath, DWORD dwSize, DWORD dwFilter)
2532c2c66affSColin Finck {
2533c2c66affSColin Finck BOOL ret = FALSE;
2534c2c66affSColin Finck LPWSTR path = heap_strdupAtoW(lpszCachePath);
2535c2c66affSColin Finck if (lpszCachePath == NULL || path != NULL)
2536c2c66affSColin Finck ret = FreeUrlCacheSpaceW(path, dwSize, dwFilter);
2537c2c66affSColin Finck heap_free(path);
2538c2c66affSColin Finck return ret;
2539c2c66affSColin Finck }
2540c2c66affSColin Finck
2541c2c66affSColin Finck /***********************************************************************
2542c2c66affSColin Finck * UnlockUrlCacheEntryFileA (WININET.@)
2543c2c66affSColin Finck *
2544c2c66affSColin Finck */
UnlockUrlCacheEntryFileA(LPCSTR lpszUrlName,DWORD dwReserved)2545c2c66affSColin Finck BOOL WINAPI UnlockUrlCacheEntryFileA(LPCSTR lpszUrlName, DWORD dwReserved)
2546c2c66affSColin Finck {
2547c2c66affSColin Finck urlcache_header *pHeader;
2548c2c66affSColin Finck struct hash_entry *pHashEntry;
2549c2c66affSColin Finck entry_header *pEntry;
2550c2c66affSColin Finck entry_url * pUrlEntry;
2551c2c66affSColin Finck cache_container *pContainer;
2552c2c66affSColin Finck DWORD error;
2553c2c66affSColin Finck
2554c2c66affSColin Finck TRACE("(%s, 0x%08x)\n", debugstr_a(lpszUrlName), dwReserved);
2555c2c66affSColin Finck
2556c2c66affSColin Finck if (dwReserved)
2557c2c66affSColin Finck {
2558c2c66affSColin Finck ERR("dwReserved != 0\n");
2559c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
2560c2c66affSColin Finck return FALSE;
2561c2c66affSColin Finck }
2562c2c66affSColin Finck
2563c2c66affSColin Finck error = cache_containers_find(lpszUrlName, &pContainer);
2564c2c66affSColin Finck if (error != ERROR_SUCCESS)
2565c2c66affSColin Finck {
2566c2c66affSColin Finck SetLastError(error);
2567c2c66affSColin Finck return FALSE;
2568c2c66affSColin Finck }
2569c2c66affSColin Finck
2570c2c66affSColin Finck error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
2571c2c66affSColin Finck if (error != ERROR_SUCCESS)
2572c2c66affSColin Finck {
2573c2c66affSColin Finck SetLastError(error);
2574c2c66affSColin Finck return FALSE;
2575c2c66affSColin Finck }
2576c2c66affSColin Finck
2577c2c66affSColin Finck if (!(pHeader = cache_container_lock_index(pContainer)))
2578c2c66affSColin Finck return FALSE;
2579c2c66affSColin Finck
2580c2c66affSColin Finck if (!urlcache_find_hash_entry(pHeader, lpszUrlName, &pHashEntry))
2581c2c66affSColin Finck {
2582c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
2583c2c66affSColin Finck TRACE("entry %s not found!\n", debugstr_a(lpszUrlName));
2584c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
2585c2c66affSColin Finck return FALSE;
2586c2c66affSColin Finck }
2587c2c66affSColin Finck
2588c2c66affSColin Finck pEntry = (entry_header*)((LPBYTE)pHeader + pHashEntry->offset);
2589c2c66affSColin Finck if (pEntry->signature != URL_SIGNATURE)
2590c2c66affSColin Finck {
2591c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
2592c2c66affSColin Finck FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->signature, sizeof(DWORD)));
2593c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
2594c2c66affSColin Finck return FALSE;
2595c2c66affSColin Finck }
2596c2c66affSColin Finck
2597c2c66affSColin Finck pUrlEntry = (entry_url *)pEntry;
2598c2c66affSColin Finck
2599c2c66affSColin Finck if (pUrlEntry->use_count == 0)
2600c2c66affSColin Finck {
2601c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
2602c2c66affSColin Finck return FALSE;
2603c2c66affSColin Finck }
2604c2c66affSColin Finck pUrlEntry->use_count--;
2605c2c66affSColin Finck if (!pUrlEntry->use_count)
2606c2c66affSColin Finck {
2607c2c66affSColin Finck urlcache_hash_entry_set_flags(pHashEntry, HASHTABLE_URL);
2608c2c66affSColin Finck if (pUrlEntry->cache_entry_type & PENDING_DELETE_CACHE_ENTRY)
2609c2c66affSColin Finck urlcache_entry_delete(pContainer, pHeader, pHashEntry);
2610c2c66affSColin Finck }
2611c2c66affSColin Finck
2612c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
2613c2c66affSColin Finck
2614c2c66affSColin Finck return TRUE;
2615c2c66affSColin Finck }
2616c2c66affSColin Finck
2617c2c66affSColin Finck /***********************************************************************
2618c2c66affSColin Finck * UnlockUrlCacheEntryFileW (WININET.@)
2619c2c66affSColin Finck *
2620c2c66affSColin Finck */
UnlockUrlCacheEntryFileW(LPCWSTR lpszUrlName,DWORD dwReserved)2621c2c66affSColin Finck BOOL WINAPI UnlockUrlCacheEntryFileW(LPCWSTR lpszUrlName, DWORD dwReserved)
2622c2c66affSColin Finck {
2623c2c66affSColin Finck char *url;
2624c2c66affSColin Finck BOOL ret;
2625c2c66affSColin Finck
2626c2c66affSColin Finck if(!urlcache_encode_url_alloc(lpszUrlName, &url))
2627c2c66affSColin Finck return FALSE;
2628c2c66affSColin Finck
2629c2c66affSColin Finck ret = UnlockUrlCacheEntryFileA(url, dwReserved);
2630c2c66affSColin Finck heap_free(url);
2631c2c66affSColin Finck return ret;
2632c2c66affSColin Finck }
2633c2c66affSColin Finck
urlcache_entry_create(const char * url,const char * ext,WCHAR * full_path)2634c2c66affSColin Finck static BOOL urlcache_entry_create(const char *url, const char *ext, WCHAR *full_path)
2635c2c66affSColin Finck {
2636c2c66affSColin Finck cache_container *container;
2637c2c66affSColin Finck urlcache_header *header;
2638c2c66affSColin Finck char file_name[MAX_PATH];
2639c2c66affSColin Finck WCHAR extW[MAX_PATH];
2640c2c66affSColin Finck BYTE cache_dir;
2641c2c66affSColin Finck LONG full_path_len, ext_len = 0;
2642c2c66affSColin Finck BOOL generate_name = FALSE;
2643c2c66affSColin Finck DWORD error;
2644c2c66affSColin Finck HANDLE file;
2645c2c66affSColin Finck FILETIME ft;
2646c2c66affSColin Finck URL_COMPONENTSA uc;
2647c2c66affSColin Finck int i;
2648c2c66affSColin Finck
2649c2c66affSColin Finck TRACE("(%s, %s, %p)\n", debugstr_a(url), debugstr_a(ext), full_path);
2650c2c66affSColin Finck
2651c2c66affSColin Finck memset(&uc, 0, sizeof(uc));
2652c2c66affSColin Finck uc.dwStructSize = sizeof(uc);
2653c2c66affSColin Finck uc.dwUrlPathLength = 1;
2654c2c66affSColin Finck uc.dwExtraInfoLength = 1;
2655c2c66affSColin Finck if(!InternetCrackUrlA(url, 0, 0, &uc))
2656c2c66affSColin Finck uc.dwUrlPathLength = 0;
2657c2c66affSColin Finck
2658c2c66affSColin Finck if(!uc.dwUrlPathLength) {
2659c2c66affSColin Finck file_name[0] = 0;
2660c2c66affSColin Finck }else {
2661c2c66affSColin Finck char *p, *e;
2662c2c66affSColin Finck
2663c2c66affSColin Finck p = e = uc.lpszUrlPath+uc.dwUrlPathLength;
2664c2c66affSColin Finck while(p>uc.lpszUrlPath && *(p-1)!='/' && *(p-1)!='\\' && *(p-1)!='.')
2665c2c66affSColin Finck p--;
2666c2c66affSColin Finck if(p>uc.lpszUrlPath && *(p-1)=='.') {
2667c2c66affSColin Finck e = p-1;
2668c2c66affSColin Finck while(p>uc.lpszUrlPath && *(p-1)!='/' && *(p-1)!='\\')
2669c2c66affSColin Finck p--;
2670c2c66affSColin Finck }
2671c2c66affSColin Finck
2672c2c66affSColin Finck if(e-p >= MAX_PATH)
2673c2c66affSColin Finck e = p+MAX_PATH-1;
2674c2c66affSColin Finck memcpy(file_name, p, e-p);
2675c2c66affSColin Finck file_name[e-p] = 0;
2676c2c66affSColin Finck
2677c2c66affSColin Finck for(p=file_name; *p; p++) {
2678c2c66affSColin Finck switch(*p) {
2679c2c66affSColin Finck case '<': case '>':
2680c2c66affSColin Finck case ':': case '"':
2681c2c66affSColin Finck case '|': case '?':
2682c2c66affSColin Finck case '*':
2683c2c66affSColin Finck *p = '_'; break;
2684c2c66affSColin Finck default: break;
2685c2c66affSColin Finck }
2686c2c66affSColin Finck }
2687c2c66affSColin Finck }
2688c2c66affSColin Finck
2689c2c66affSColin Finck if(!file_name[0])
2690c2c66affSColin Finck generate_name = TRUE;
2691c2c66affSColin Finck
2692c2c66affSColin Finck error = cache_containers_find(url, &container);
2693c2c66affSColin Finck if(error != ERROR_SUCCESS) {
2694c2c66affSColin Finck SetLastError(error);
2695c2c66affSColin Finck return FALSE;
2696c2c66affSColin Finck }
2697c2c66affSColin Finck
2698c2c66affSColin Finck error = cache_container_open_index(container, MIN_BLOCK_NO);
2699c2c66affSColin Finck if(error != ERROR_SUCCESS) {
2700c2c66affSColin Finck SetLastError(error);
2701c2c66affSColin Finck return FALSE;
2702c2c66affSColin Finck }
2703c2c66affSColin Finck
2704c2c66affSColin Finck if(!(header = cache_container_lock_index(container)))
2705c2c66affSColin Finck return FALSE;
2706c2c66affSColin Finck
2707c2c66affSColin Finck if(header->dirs_no)
2708c2c66affSColin Finck cache_dir = (BYTE)(rand() % header->dirs_no);
2709c2c66affSColin Finck else
2710c2c66affSColin Finck cache_dir = CACHE_CONTAINER_NO_SUBDIR;
2711c2c66affSColin Finck
2712c2c66affSColin Finck full_path_len = MAX_PATH * sizeof(WCHAR);
2713c2c66affSColin Finck if(!urlcache_create_file_pathW(container, header, file_name, cache_dir, full_path, &full_path_len, TRUE)) {
2714c2c66affSColin Finck WARN("Failed to get full path for filename %s, needed %u bytes.\n",
2715c2c66affSColin Finck debugstr_a(file_name), full_path_len);
2716c2c66affSColin Finck cache_container_unlock_index(container, header);
2717c2c66affSColin Finck return FALSE;
2718c2c66affSColin Finck }
2719c2c66affSColin Finck full_path_len = full_path_len/sizeof(WCHAR) - 1;
2720c2c66affSColin Finck
2721c2c66affSColin Finck cache_container_unlock_index(container, header);
2722c2c66affSColin Finck
2723c2c66affSColin Finck if(ext) {
2724c2c66affSColin Finck WCHAR *p;
2725c2c66affSColin Finck
2726c2c66affSColin Finck extW[0] = '.';
2727c2c66affSColin Finck ext_len = MultiByteToWideChar(CP_ACP, 0, ext, -1, extW+1, MAX_PATH-1);
2728c2c66affSColin Finck
2729c2c66affSColin Finck for(p=extW; *p; p++) {
2730c2c66affSColin Finck switch(*p) {
2731c2c66affSColin Finck case '<': case '>':
2732c2c66affSColin Finck case ':': case '"':
2733c2c66affSColin Finck case '|': case '?':
2734c2c66affSColin Finck case '*':
2735c2c66affSColin Finck *p = '_'; break;
2736c2c66affSColin Finck default: break;
2737c2c66affSColin Finck }
2738c2c66affSColin Finck }
2739c2c66affSColin Finck if(p[-1]==' ' || p[-1]=='.')
2740c2c66affSColin Finck p[-1] = '_';
2741c2c66affSColin Finck }else {
2742c2c66affSColin Finck extW[0] = '\0';
2743c2c66affSColin Finck }
2744c2c66affSColin Finck
2745c2c66affSColin Finck if(!generate_name && full_path_len+5+ext_len>=MAX_PATH) { /* strlen("[255]") = 5 */
2746c2c66affSColin Finck full_path_len = MAX_PATH-5-ext_len-1;
2747c2c66affSColin Finck }
2748c2c66affSColin Finck
2749c2c66affSColin Finck for(i=0; i<255 && !generate_name; i++) {
2750*e152f78aSwinesync wsprintfW(full_path+full_path_len, L"[%u]%s", i, extW);
2751c2c66affSColin Finck
2752c2c66affSColin Finck TRACE("Trying: %s\n", debugstr_w(full_path));
2753c2c66affSColin Finck file = CreateFileW(full_path, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
2754c2c66affSColin Finck if(file != INVALID_HANDLE_VALUE) {
2755c2c66affSColin Finck CloseHandle(file);
2756c2c66affSColin Finck return TRUE;
2757c2c66affSColin Finck }
2758c2c66affSColin Finck }
2759c2c66affSColin Finck
2760c2c66affSColin Finck if(full_path_len+8+ext_len >= MAX_PATH)
2761c2c66affSColin Finck full_path_len = MAX_PATH-8-ext_len-1;
2762c2c66affSColin Finck
2763c2c66affSColin Finck /* Try to generate random name */
2764c2c66affSColin Finck GetSystemTimeAsFileTime(&ft);
27655f12c8d7Swinesync lstrcpyW(full_path+full_path_len+8, extW);
2766c2c66affSColin Finck
2767c2c66affSColin Finck for(i=0; i<255; i++) {
2768c2c66affSColin Finck int j;
2769c2c66affSColin Finck ULONGLONG n = ft.dwHighDateTime;
2770c2c66affSColin Finck n <<= 32;
2771c2c66affSColin Finck n += ft.dwLowDateTime;
2772c2c66affSColin Finck n ^= (ULONGLONG)i<<48;
2773c2c66affSColin Finck
2774c2c66affSColin Finck for(j=0; j<8; j++) {
2775c2c66affSColin Finck int r = (n % 36);
2776c2c66affSColin Finck n /= 37;
2777c2c66affSColin Finck full_path[full_path_len+j] = (r < 10 ? '0' + r : 'A' + r - 10);
2778c2c66affSColin Finck }
2779c2c66affSColin Finck
2780c2c66affSColin Finck TRACE("Trying: %s\n", debugstr_w(full_path));
2781c2c66affSColin Finck file = CreateFileW(full_path, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
2782c2c66affSColin Finck if(file != INVALID_HANDLE_VALUE) {
2783c2c66affSColin Finck CloseHandle(file);
2784c2c66affSColin Finck return TRUE;
2785c2c66affSColin Finck }
2786c2c66affSColin Finck }
2787c2c66affSColin Finck
2788c2c66affSColin Finck WARN("Could not find a unique filename\n");
2789c2c66affSColin Finck return FALSE;
2790c2c66affSColin Finck }
2791c2c66affSColin Finck
2792c2c66affSColin Finck /***********************************************************************
2793c2c66affSColin Finck * CreateUrlCacheEntryA (WININET.@)
2794c2c66affSColin Finck *
2795c2c66affSColin Finck */
CreateUrlCacheEntryA(LPCSTR lpszUrlName,DWORD dwExpectedFileSize,LPCSTR lpszFileExtension,LPSTR lpszFileName,DWORD dwReserved)2796c2c66affSColin Finck BOOL WINAPI CreateUrlCacheEntryA(LPCSTR lpszUrlName, DWORD dwExpectedFileSize,
2797c2c66affSColin Finck LPCSTR lpszFileExtension, LPSTR lpszFileName, DWORD dwReserved)
2798c2c66affSColin Finck {
2799c2c66affSColin Finck WCHAR file_name[MAX_PATH];
2800c2c66affSColin Finck
2801c2c66affSColin Finck if(dwReserved)
2802c2c66affSColin Finck FIXME("dwReserved 0x%08x\n", dwReserved);
2803c2c66affSColin Finck
2804c2c66affSColin Finck if(!urlcache_entry_create(lpszUrlName, lpszFileExtension, file_name))
2805c2c66affSColin Finck return FALSE;
2806c2c66affSColin Finck
2807c2c66affSColin Finck if(!WideCharToMultiByte(CP_ACP, 0, file_name, -1, lpszFileName, MAX_PATH, NULL, NULL))
2808c2c66affSColin Finck return FALSE;
2809c2c66affSColin Finck return TRUE;
2810c2c66affSColin Finck }
2811c2c66affSColin Finck /***********************************************************************
2812c2c66affSColin Finck * CreateUrlCacheEntryW (WININET.@)
2813c2c66affSColin Finck *
2814c2c66affSColin Finck */
CreateUrlCacheEntryW(LPCWSTR lpszUrlName,DWORD dwExpectedFileSize,LPCWSTR lpszFileExtension,LPWSTR lpszFileName,DWORD dwReserved)2815c2c66affSColin Finck BOOL WINAPI CreateUrlCacheEntryW(LPCWSTR lpszUrlName, DWORD dwExpectedFileSize,
2816c2c66affSColin Finck LPCWSTR lpszFileExtension, LPWSTR lpszFileName, DWORD dwReserved)
2817c2c66affSColin Finck {
2818c2c66affSColin Finck char *url, *ext = NULL;
2819c2c66affSColin Finck BOOL ret;
2820c2c66affSColin Finck
2821c2c66affSColin Finck if(dwReserved)
2822c2c66affSColin Finck FIXME("dwReserved 0x%08x\n", dwReserved);
2823c2c66affSColin Finck
2824c2c66affSColin Finck if(lpszFileExtension) {
2825c2c66affSColin Finck ext = heap_strdupWtoUTF8(lpszFileExtension);
2826c2c66affSColin Finck if(!ext)
2827c2c66affSColin Finck return FALSE;
2828c2c66affSColin Finck }
2829c2c66affSColin Finck
2830c2c66affSColin Finck if(!urlcache_encode_url_alloc(lpszUrlName, &url)) {
2831c2c66affSColin Finck heap_free(ext);
2832c2c66affSColin Finck return FALSE;
2833c2c66affSColin Finck }
2834c2c66affSColin Finck
2835c2c66affSColin Finck ret = urlcache_entry_create(url, ext, lpszFileName);
2836c2c66affSColin Finck heap_free(ext);
2837c2c66affSColin Finck heap_free(url);
2838c2c66affSColin Finck return ret;
2839c2c66affSColin Finck }
2840c2c66affSColin Finck
urlcache_entry_commit(const char * url,const WCHAR * file_name,FILETIME expire_time,FILETIME modify_time,DWORD entry_type,BYTE * header_info,DWORD header_size,const char * file_ext,const char * original_url)2841c2c66affSColin Finck static BOOL urlcache_entry_commit(const char *url, const WCHAR *file_name,
2842c2c66affSColin Finck FILETIME expire_time, FILETIME modify_time, DWORD entry_type,
2843c2c66affSColin Finck BYTE *header_info, DWORD header_size, const char *file_ext,
2844c2c66affSColin Finck const char *original_url)
2845c2c66affSColin Finck {
2846c2c66affSColin Finck cache_container *container;
2847c2c66affSColin Finck urlcache_header *header;
2848c2c66affSColin Finck struct hash_entry *hash_entry;
2849c2c66affSColin Finck entry_header *entry;
2850c2c66affSColin Finck entry_url *url_entry;
2851c2c66affSColin Finck DWORD url_entry_offset;
2852c2c66affSColin Finck DWORD size = DWORD_ALIGN(sizeof(*url_entry));
2853c2c66affSColin Finck DWORD file_name_off = 0;
2854c2c66affSColin Finck DWORD header_info_off = 0;
2855c2c66affSColin Finck DWORD file_ext_off = 0;
2856c2c66affSColin Finck WIN32_FILE_ATTRIBUTE_DATA file_attr;
2857c2c66affSColin Finck LARGE_INTEGER file_size;
2858c2c66affSColin Finck BYTE dir_id;
2859c2c66affSColin Finck char file_name_no_container[MAX_PATH];
2860c2c66affSColin Finck char *local_file_name = 0;
2861c2c66affSColin Finck DWORD hit_rate = 0;
2862c2c66affSColin Finck DWORD exempt_delta = 0;
2863c2c66affSColin Finck DWORD error;
2864c2c66affSColin Finck
2865c2c66affSColin Finck TRACE("(%s, %s, ..., ..., %x, %p, %d, %s, %s)\n", debugstr_a(url), debugstr_w(file_name),
2866c2c66affSColin Finck entry_type, header_info, header_size, debugstr_a(file_ext), debugstr_a(original_url));
2867c2c66affSColin Finck
2868c2c66affSColin Finck if(entry_type & STICKY_CACHE_ENTRY && !file_name) {
2869c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
2870c2c66affSColin Finck return FALSE;
2871c2c66affSColin Finck }
2872c2c66affSColin Finck if(original_url)
2873c2c66affSColin Finck WARN(": original_url ignored\n");
2874c2c66affSColin Finck
2875c2c66affSColin Finck memset(&file_attr, 0, sizeof(file_attr));
2876c2c66affSColin Finck if(file_name) {
2877c2c66affSColin Finck if(!GetFileAttributesExW(file_name, GetFileExInfoStandard, &file_attr))
2878c2c66affSColin Finck return FALSE;
2879c2c66affSColin Finck }
2880c2c66affSColin Finck file_size.u.LowPart = file_attr.nFileSizeLow;
2881c2c66affSColin Finck file_size.u.HighPart = file_attr.nFileSizeHigh;
2882c2c66affSColin Finck
2883c2c66affSColin Finck error = cache_containers_find(url, &container);
2884c2c66affSColin Finck if(error != ERROR_SUCCESS) {
2885c2c66affSColin Finck SetLastError(error);
2886c2c66affSColin Finck return FALSE;
2887c2c66affSColin Finck }
2888c2c66affSColin Finck
2889c2c66affSColin Finck error = cache_container_open_index(container, MIN_BLOCK_NO);
2890c2c66affSColin Finck if(error != ERROR_SUCCESS) {
2891c2c66affSColin Finck SetLastError(error);
2892c2c66affSColin Finck return FALSE;
2893c2c66affSColin Finck }
2894c2c66affSColin Finck
2895c2c66affSColin Finck if(!(header = cache_container_lock_index(container)))
2896c2c66affSColin Finck return FALSE;
2897c2c66affSColin Finck
2898c2c66affSColin Finck if(urlcache_find_hash_entry(header, url, &hash_entry)) {
2899c2c66affSColin Finck entry_url *url_entry = (entry_url*)((LPBYTE)header + hash_entry->offset);
2900c2c66affSColin Finck
2901c2c66affSColin Finck if(urlcache_hash_entry_is_locked(hash_entry, url_entry)) {
2902c2c66affSColin Finck TRACE("Trying to overwrite locked entry\n");
2903c2c66affSColin Finck cache_container_unlock_index(container, header);
2904c2c66affSColin Finck SetLastError(ERROR_SHARING_VIOLATION);
2905c2c66affSColin Finck return FALSE;
2906c2c66affSColin Finck }
2907c2c66affSColin Finck
2908c2c66affSColin Finck hit_rate = url_entry->hit_rate;
2909c2c66affSColin Finck exempt_delta = url_entry->exempt_delta;
2910c2c66affSColin Finck urlcache_entry_delete(container, header, hash_entry);
2911c2c66affSColin Finck }
2912c2c66affSColin Finck
2913c2c66affSColin Finck if(header->dirs_no)
2914c2c66affSColin Finck dir_id = 0;
2915c2c66affSColin Finck else
2916c2c66affSColin Finck dir_id = CACHE_CONTAINER_NO_SUBDIR;
2917c2c66affSColin Finck
2918c2c66affSColin Finck if(file_name) {
2919c2c66affSColin Finck BOOL bFound = FALSE;
2920c2c66affSColin Finck
29215f12c8d7Swinesync if(wcsncmp(file_name, container->path, lstrlenW(container->path))) {
2922c2c66affSColin Finck ERR("path %s must begin with cache content path %s\n", debugstr_w(file_name), debugstr_w(container->path));
2923c2c66affSColin Finck cache_container_unlock_index(container, header);
2924c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
2925c2c66affSColin Finck return FALSE;
2926c2c66affSColin Finck }
2927c2c66affSColin Finck
2928c2c66affSColin Finck /* skip container path prefix */
2929c2c66affSColin Finck file_name += lstrlenW(container->path);
2930c2c66affSColin Finck
2931c2c66affSColin Finck WideCharToMultiByte(CP_ACP, 0, file_name, -1, file_name_no_container, MAX_PATH, NULL, NULL);
2932c2c66affSColin Finck local_file_name = file_name_no_container;
2933c2c66affSColin Finck
2934c2c66affSColin Finck if(header->dirs_no) {
2935c2c66affSColin Finck for(dir_id = 0; dir_id < header->dirs_no; dir_id++) {
2936c2c66affSColin Finck if(!strncmp(header->directory_data[dir_id].name, local_file_name, DIR_LENGTH)) {
2937c2c66affSColin Finck bFound = TRUE;
2938c2c66affSColin Finck break;
2939c2c66affSColin Finck }
2940c2c66affSColin Finck }
2941c2c66affSColin Finck
2942c2c66affSColin Finck if(!bFound) {
2943c2c66affSColin Finck ERR("cache directory not found in path %s\n", debugstr_w(file_name));
2944c2c66affSColin Finck cache_container_unlock_index(container, header);
2945c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
2946c2c66affSColin Finck return FALSE;
2947c2c66affSColin Finck }
2948c2c66affSColin Finck
2949c2c66affSColin Finck file_name += DIR_LENGTH + 1;
2950c2c66affSColin Finck local_file_name += DIR_LENGTH + 1;
2951c2c66affSColin Finck }
2952c2c66affSColin Finck }
2953c2c66affSColin Finck
2954c2c66affSColin Finck size = DWORD_ALIGN(size + strlen(url) + 1);
2955c2c66affSColin Finck if(file_name) {
2956c2c66affSColin Finck file_name_off = size;
2957c2c66affSColin Finck size = DWORD_ALIGN(size + strlen(local_file_name) + 1);
2958c2c66affSColin Finck }
2959c2c66affSColin Finck if(header_info && header_size) {
2960c2c66affSColin Finck header_info_off = size;
2961c2c66affSColin Finck size = DWORD_ALIGN(size + header_size);
2962c2c66affSColin Finck }
2963c2c66affSColin Finck if(file_ext && (file_ext_off = strlen(file_ext))) {
2964c2c66affSColin Finck DWORD len = file_ext_off;
2965c2c66affSColin Finck
2966c2c66affSColin Finck file_ext_off = size;
2967c2c66affSColin Finck size = DWORD_ALIGN(size + len + 1);
2968c2c66affSColin Finck }
2969c2c66affSColin Finck
2970c2c66affSColin Finck /* round up to next block */
2971c2c66affSColin Finck if(size % BLOCKSIZE) {
2972c2c66affSColin Finck size -= size % BLOCKSIZE;
2973c2c66affSColin Finck size += BLOCKSIZE;
2974c2c66affSColin Finck }
2975c2c66affSColin Finck
2976c2c66affSColin Finck error = urlcache_entry_alloc(header, size / BLOCKSIZE, &entry);
2977c2c66affSColin Finck while(error == ERROR_HANDLE_DISK_FULL) {
2978c2c66affSColin Finck error = cache_container_clean_index(container, &header);
2979c2c66affSColin Finck if(error == ERROR_SUCCESS)
2980c2c66affSColin Finck error = urlcache_entry_alloc(header, size / BLOCKSIZE, &entry);
2981c2c66affSColin Finck }
2982c2c66affSColin Finck if(error != ERROR_SUCCESS) {
2983c2c66affSColin Finck cache_container_unlock_index(container, header);
2984c2c66affSColin Finck SetLastError(error);
2985c2c66affSColin Finck return FALSE;
2986c2c66affSColin Finck }
2987c2c66affSColin Finck
2988c2c66affSColin Finck /* FindFirstFreeEntry fills in blocks used */
2989c2c66affSColin Finck url_entry = (entry_url *)entry;
2990c2c66affSColin Finck url_entry_offset = (LPBYTE)url_entry - (LPBYTE)header;
2991c2c66affSColin Finck url_entry->header.signature = URL_SIGNATURE;
2992c2c66affSColin Finck url_entry->cache_dir = dir_id;
2993c2c66affSColin Finck url_entry->cache_entry_type = entry_type | container->default_entry_type;
2994c2c66affSColin Finck url_entry->header_info_size = header_size;
2995c2c66affSColin Finck if((entry_type & STICKY_CACHE_ENTRY) && !exempt_delta) {
2996c2c66affSColin Finck /* Sticky entries have a default exempt time of one day */
2997c2c66affSColin Finck exempt_delta = 86400;
2998c2c66affSColin Finck }
2999c2c66affSColin Finck url_entry->exempt_delta = exempt_delta;
3000c2c66affSColin Finck url_entry->hit_rate = hit_rate+1;
3001c2c66affSColin Finck url_entry->file_extension_off = file_ext_off;
3002c2c66affSColin Finck url_entry->header_info_off = header_info_off;
3003c2c66affSColin Finck url_entry->local_name_off = file_name_off;
3004c2c66affSColin Finck url_entry->url_off = DWORD_ALIGN(sizeof(*url_entry));
3005c2c66affSColin Finck url_entry->size.QuadPart = file_size.QuadPart;
3006c2c66affSColin Finck url_entry->use_count = 0;
3007c2c66affSColin Finck GetSystemTimeAsFileTime(&url_entry->access_time);
3008c2c66affSColin Finck url_entry->modification_time = modify_time;
3009c2c66affSColin Finck file_time_to_dos_date_time(&url_entry->access_time, &url_entry->sync_date, &url_entry->sync_time);
3010c2c66affSColin Finck file_time_to_dos_date_time(&expire_time, &url_entry->expire_date, &url_entry->expire_time);
3011c2c66affSColin Finck file_time_to_dos_date_time(&file_attr.ftLastWriteTime, &url_entry->write_date, &url_entry->write_time);
3012c2c66affSColin Finck
3013c2c66affSColin Finck /*** Unknowns ***/
3014c2c66affSColin Finck url_entry->unk1 = 0;
3015c2c66affSColin Finck url_entry->unk2 = 0;
3016c2c66affSColin Finck url_entry->unk3 = 0x60;
3017c2c66affSColin Finck url_entry->unk4 = 0;
3018c2c66affSColin Finck url_entry->unk5 = 0x1010;
3019c2c66affSColin Finck url_entry->unk7 = 0;
3020c2c66affSColin Finck url_entry->unk8 = 0;
3021c2c66affSColin Finck
3022c2c66affSColin Finck
3023c2c66affSColin Finck strcpy((LPSTR)url_entry + url_entry->url_off, url);
3024c2c66affSColin Finck if(file_name_off)
3025c2c66affSColin Finck strcpy((LPSTR)((LPBYTE)url_entry + file_name_off), local_file_name);
3026c2c66affSColin Finck if(header_info_off)
3027c2c66affSColin Finck memcpy((LPBYTE)url_entry + header_info_off, header_info, header_size);
3028c2c66affSColin Finck if(file_ext_off)
3029c2c66affSColin Finck strcpy((LPSTR)((LPBYTE)url_entry + file_ext_off), file_ext);
3030c2c66affSColin Finck
3031c2c66affSColin Finck error = urlcache_hash_entry_create(header, url, url_entry_offset, HASHTABLE_URL);
3032c2c66affSColin Finck while(error == ERROR_HANDLE_DISK_FULL) {
3033c2c66affSColin Finck error = cache_container_clean_index(container, &header);
3034c2c66affSColin Finck if(error == ERROR_SUCCESS) {
3035c2c66affSColin Finck url_entry = (entry_url *)((LPBYTE)header + url_entry_offset);
3036c2c66affSColin Finck error = urlcache_hash_entry_create(header, url,
3037c2c66affSColin Finck url_entry_offset, HASHTABLE_URL);
3038c2c66affSColin Finck }
3039c2c66affSColin Finck }
3040c2c66affSColin Finck if(error != ERROR_SUCCESS) {
3041c2c66affSColin Finck urlcache_entry_free(header, &url_entry->header);
3042c2c66affSColin Finck cache_container_unlock_index(container, header);
3043c2c66affSColin Finck SetLastError(error);
3044c2c66affSColin Finck return FALSE;
3045c2c66affSColin Finck }
3046c2c66affSColin Finck
3047c2c66affSColin Finck if(url_entry->cache_dir < header->dirs_no)
3048c2c66affSColin Finck header->directory_data[url_entry->cache_dir].files_no++;
3049c2c66affSColin Finck if(entry_type & STICKY_CACHE_ENTRY)
3050c2c66affSColin Finck header->exempt_usage.QuadPart += file_size.QuadPart;
3051c2c66affSColin Finck else
3052c2c66affSColin Finck header->cache_usage.QuadPart += file_size.QuadPart;
3053c2c66affSColin Finck if(header->cache_usage.QuadPart+header->exempt_usage.QuadPart > header->cache_limit.QuadPart)
3054c2c66affSColin Finck handle_full_cache();
3055c2c66affSColin Finck
3056c2c66affSColin Finck cache_container_unlock_index(container, header);
3057c2c66affSColin Finck return TRUE;
3058c2c66affSColin Finck }
3059c2c66affSColin Finck
3060c2c66affSColin Finck /***********************************************************************
3061c2c66affSColin Finck * CommitUrlCacheEntryA (WININET.@)
3062c2c66affSColin Finck */
CommitUrlCacheEntryA(LPCSTR lpszUrlName,LPCSTR lpszLocalFileName,FILETIME ExpireTime,FILETIME LastModifiedTime,DWORD CacheEntryType,LPBYTE lpHeaderInfo,DWORD dwHeaderSize,LPCSTR lpszFileExtension,LPCSTR lpszOriginalUrl)3063c2c66affSColin Finck BOOL WINAPI CommitUrlCacheEntryA(LPCSTR lpszUrlName, LPCSTR lpszLocalFileName,
3064c2c66affSColin Finck FILETIME ExpireTime, FILETIME LastModifiedTime, DWORD CacheEntryType,
3065c2c66affSColin Finck LPBYTE lpHeaderInfo, DWORD dwHeaderSize, LPCSTR lpszFileExtension, LPCSTR lpszOriginalUrl)
3066c2c66affSColin Finck {
3067c2c66affSColin Finck WCHAR *file_name = NULL;
3068c2c66affSColin Finck BOOL ret;
3069c2c66affSColin Finck
3070c2c66affSColin Finck if(lpszLocalFileName) {
3071c2c66affSColin Finck file_name = heap_strdupAtoW(lpszLocalFileName);
3072c2c66affSColin Finck if(!file_name)
3073c2c66affSColin Finck return FALSE;
3074c2c66affSColin Finck }
3075c2c66affSColin Finck
3076c2c66affSColin Finck ret = urlcache_entry_commit(lpszUrlName, file_name, ExpireTime, LastModifiedTime,
3077c2c66affSColin Finck CacheEntryType, lpHeaderInfo, dwHeaderSize, lpszFileExtension, lpszOriginalUrl);
3078c2c66affSColin Finck heap_free(file_name);
3079c2c66affSColin Finck return ret;
3080c2c66affSColin Finck }
3081c2c66affSColin Finck
3082c2c66affSColin Finck /***********************************************************************
3083c2c66affSColin Finck * CommitUrlCacheEntryW (WININET.@)
3084c2c66affSColin Finck */
CommitUrlCacheEntryW(LPCWSTR lpszUrlName,LPCWSTR lpszLocalFileName,FILETIME ExpireTime,FILETIME LastModifiedTime,DWORD CacheEntryType,LPWSTR lpHeaderInfo,DWORD dwHeaderSize,LPCWSTR lpszFileExtension,LPCWSTR lpszOriginalUrl)3085c2c66affSColin Finck BOOL WINAPI CommitUrlCacheEntryW(LPCWSTR lpszUrlName, LPCWSTR lpszLocalFileName,
3086c2c66affSColin Finck FILETIME ExpireTime, FILETIME LastModifiedTime, DWORD CacheEntryType,
3087c2c66affSColin Finck LPWSTR lpHeaderInfo, DWORD dwHeaderSize, LPCWSTR lpszFileExtension, LPCWSTR lpszOriginalUrl)
3088c2c66affSColin Finck {
3089c2c66affSColin Finck char *url, *original_url=NULL, *file_ext=NULL, *header_info=NULL;
3090c2c66affSColin Finck BOOL ret;
3091c2c66affSColin Finck
3092c2c66affSColin Finck if(!urlcache_encode_url_alloc(lpszUrlName, &url))
3093c2c66affSColin Finck return FALSE;
3094c2c66affSColin Finck
3095c2c66affSColin Finck if(lpHeaderInfo) {
3096c2c66affSColin Finck header_info = heap_strdupWtoUTF8(lpHeaderInfo);
3097c2c66affSColin Finck if(!header_info) {
3098c2c66affSColin Finck heap_free(url);
3099c2c66affSColin Finck return FALSE;
3100c2c66affSColin Finck }
3101c2c66affSColin Finck dwHeaderSize = strlen(header_info);
3102c2c66affSColin Finck }
3103c2c66affSColin Finck
3104c2c66affSColin Finck if(lpszFileExtension) {
3105c2c66affSColin Finck file_ext = heap_strdupWtoA(lpszFileExtension);
3106c2c66affSColin Finck if(!file_ext) {
3107c2c66affSColin Finck heap_free(url);
3108c2c66affSColin Finck heap_free(header_info);
3109c2c66affSColin Finck return FALSE;
3110c2c66affSColin Finck }
3111c2c66affSColin Finck }
3112c2c66affSColin Finck
3113c2c66affSColin Finck if(lpszOriginalUrl && !urlcache_encode_url_alloc(lpszOriginalUrl, &original_url)) {
3114c2c66affSColin Finck heap_free(url);
3115c2c66affSColin Finck heap_free(header_info);
3116c2c66affSColin Finck heap_free(file_ext);
3117c2c66affSColin Finck return FALSE;
3118c2c66affSColin Finck }
3119c2c66affSColin Finck
3120c2c66affSColin Finck ret = urlcache_entry_commit(url, lpszLocalFileName, ExpireTime, LastModifiedTime,
3121c2c66affSColin Finck CacheEntryType, (BYTE*)header_info, dwHeaderSize, file_ext, original_url);
3122c2c66affSColin Finck heap_free(url);
3123c2c66affSColin Finck heap_free(header_info);
3124c2c66affSColin Finck heap_free(file_ext);
3125c2c66affSColin Finck heap_free(original_url);
3126c2c66affSColin Finck return ret;
3127c2c66affSColin Finck }
3128c2c66affSColin Finck
3129c2c66affSColin Finck /***********************************************************************
3130c2c66affSColin Finck * ReadUrlCacheEntryStream (WININET.@)
3131c2c66affSColin Finck *
3132c2c66affSColin Finck */
ReadUrlCacheEntryStream(IN HANDLE hUrlCacheStream,IN DWORD dwLocation,IN OUT LPVOID lpBuffer,IN OUT LPDWORD lpdwLen,IN DWORD dwReserved)3133c2c66affSColin Finck BOOL WINAPI ReadUrlCacheEntryStream(
3134c2c66affSColin Finck IN HANDLE hUrlCacheStream,
3135c2c66affSColin Finck IN DWORD dwLocation,
3136c2c66affSColin Finck IN OUT LPVOID lpBuffer,
3137c2c66affSColin Finck IN OUT LPDWORD lpdwLen,
3138c2c66affSColin Finck IN DWORD dwReserved
3139c2c66affSColin Finck )
3140c2c66affSColin Finck {
3141c2c66affSColin Finck /* Get handle to file from 'stream' */
3142c2c66affSColin Finck stream_handle *pStream = (stream_handle*)hUrlCacheStream;
3143c2c66affSColin Finck
3144c2c66affSColin Finck if (dwReserved != 0)
3145c2c66affSColin Finck {
3146c2c66affSColin Finck ERR("dwReserved != 0\n");
3147c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
3148c2c66affSColin Finck return FALSE;
3149c2c66affSColin Finck }
3150c2c66affSColin Finck
3151c2c66affSColin Finck if (IsBadReadPtr(pStream, sizeof(*pStream)) || IsBadStringPtrA(pStream->url, INTERNET_MAX_URL_LENGTH))
3152c2c66affSColin Finck {
3153c2c66affSColin Finck SetLastError(ERROR_INVALID_HANDLE);
3154c2c66affSColin Finck return FALSE;
3155c2c66affSColin Finck }
3156c2c66affSColin Finck
3157c2c66affSColin Finck if (SetFilePointer(pStream->file, dwLocation, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
3158c2c66affSColin Finck return FALSE;
3159c2c66affSColin Finck return ReadFile(pStream->file, lpBuffer, *lpdwLen, lpdwLen, NULL);
3160c2c66affSColin Finck }
3161c2c66affSColin Finck
3162c2c66affSColin Finck /***********************************************************************
3163c2c66affSColin Finck * RetrieveUrlCacheEntryStreamA (WININET.@)
3164c2c66affSColin Finck *
3165c2c66affSColin Finck */
RetrieveUrlCacheEntryStreamA(LPCSTR lpszUrlName,LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,LPDWORD lpdwCacheEntryInfoBufferSize,BOOL fRandomRead,DWORD dwReserved)3166c2c66affSColin Finck HANDLE WINAPI RetrieveUrlCacheEntryStreamA(LPCSTR lpszUrlName,
3167c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
3168c2c66affSColin Finck LPDWORD lpdwCacheEntryInfoBufferSize, BOOL fRandomRead, DWORD dwReserved)
3169c2c66affSColin Finck {
3170c2c66affSColin Finck /* NOTE: this is not the same as the way that the native
3171c2c66affSColin Finck * version allocates 'stream' handles. I did it this way
3172c2c66affSColin Finck * as it is much easier and no applications should depend
3173c2c66affSColin Finck * on this behaviour. (Native version appears to allocate
3174c2c66affSColin Finck * indices into a table)
3175c2c66affSColin Finck */
3176c2c66affSColin Finck stream_handle *stream;
3177c2c66affSColin Finck HANDLE file;
3178c2c66affSColin Finck
3179c2c66affSColin Finck TRACE("(%s, %p, %p, %x, 0x%08x)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo,
3180c2c66affSColin Finck lpdwCacheEntryInfoBufferSize, fRandomRead, dwReserved);
3181c2c66affSColin Finck
3182c2c66affSColin Finck if(!RetrieveUrlCacheEntryFileA(lpszUrlName, lpCacheEntryInfo,
3183c2c66affSColin Finck lpdwCacheEntryInfoBufferSize, dwReserved))
3184c2c66affSColin Finck return NULL;
3185c2c66affSColin Finck
3186c2c66affSColin Finck file = CreateFileA(lpCacheEntryInfo->lpszLocalFileName, GENERIC_READ, FILE_SHARE_READ,
3187c2c66affSColin Finck NULL, OPEN_EXISTING, fRandomRead ? FILE_FLAG_RANDOM_ACCESS : 0, NULL);
3188c2c66affSColin Finck if(file == INVALID_HANDLE_VALUE) {
3189c2c66affSColin Finck UnlockUrlCacheEntryFileA(lpszUrlName, 0);
3190c2c66affSColin Finck return NULL;
3191c2c66affSColin Finck }
3192c2c66affSColin Finck
3193c2c66affSColin Finck /* allocate handle storage space */
3194c2c66affSColin Finck stream = heap_alloc(sizeof(stream_handle) + strlen(lpszUrlName) * sizeof(CHAR));
3195c2c66affSColin Finck if(!stream) {
3196c2c66affSColin Finck CloseHandle(file);
3197c2c66affSColin Finck UnlockUrlCacheEntryFileA(lpszUrlName, 0);
3198c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
3199c2c66affSColin Finck return NULL;
3200c2c66affSColin Finck }
3201c2c66affSColin Finck
3202c2c66affSColin Finck stream->file = file;
3203c2c66affSColin Finck strcpy(stream->url, lpszUrlName);
3204c2c66affSColin Finck return stream;
3205c2c66affSColin Finck }
3206c2c66affSColin Finck
3207c2c66affSColin Finck /***********************************************************************
3208c2c66affSColin Finck * RetrieveUrlCacheEntryStreamW (WININET.@)
3209c2c66affSColin Finck *
3210c2c66affSColin Finck */
RetrieveUrlCacheEntryStreamW(LPCWSTR lpszUrlName,LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,LPDWORD lpdwCacheEntryInfoBufferSize,BOOL fRandomRead,DWORD dwReserved)3211c2c66affSColin Finck HANDLE WINAPI RetrieveUrlCacheEntryStreamW(LPCWSTR lpszUrlName,
3212c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
3213c2c66affSColin Finck LPDWORD lpdwCacheEntryInfoBufferSize, BOOL fRandomRead, DWORD dwReserved)
3214c2c66affSColin Finck {
3215c2c66affSColin Finck DWORD len;
3216c2c66affSColin Finck /* NOTE: this is not the same as the way that the native
3217c2c66affSColin Finck * version allocates 'stream' handles. I did it this way
3218c2c66affSColin Finck * as it is much easier and no applications should depend
3219c2c66affSColin Finck * on this behaviour. (Native version appears to allocate
3220c2c66affSColin Finck * indices into a table)
3221c2c66affSColin Finck */
3222c2c66affSColin Finck stream_handle *stream;
3223c2c66affSColin Finck HANDLE file;
3224c2c66affSColin Finck
3225c2c66affSColin Finck TRACE("(%s, %p, %p, %x, 0x%08x)\n", debugstr_w(lpszUrlName), lpCacheEntryInfo,
3226c2c66affSColin Finck lpdwCacheEntryInfoBufferSize, fRandomRead, dwReserved);
3227c2c66affSColin Finck
3228c2c66affSColin Finck if(!(len = urlcache_encode_url(lpszUrlName, NULL, 0)))
3229c2c66affSColin Finck return NULL;
3230c2c66affSColin Finck
3231c2c66affSColin Finck if(!RetrieveUrlCacheEntryFileW(lpszUrlName, lpCacheEntryInfo,
3232c2c66affSColin Finck lpdwCacheEntryInfoBufferSize, dwReserved))
3233c2c66affSColin Finck return NULL;
3234c2c66affSColin Finck
3235c2c66affSColin Finck file = CreateFileW(lpCacheEntryInfo->lpszLocalFileName, GENERIC_READ, FILE_SHARE_READ,
3236c2c66affSColin Finck NULL, OPEN_EXISTING, fRandomRead ? FILE_FLAG_RANDOM_ACCESS : 0, NULL);
3237c2c66affSColin Finck if(file == INVALID_HANDLE_VALUE) {
3238c2c66affSColin Finck UnlockUrlCacheEntryFileW(lpszUrlName, 0);
3239c2c66affSColin Finck return NULL;
3240c2c66affSColin Finck }
3241c2c66affSColin Finck
3242c2c66affSColin Finck /* allocate handle storage space */
3243c2c66affSColin Finck stream = heap_alloc(sizeof(stream_handle) + len*sizeof(WCHAR));
3244c2c66affSColin Finck if(!stream) {
3245c2c66affSColin Finck CloseHandle(file);
3246c2c66affSColin Finck UnlockUrlCacheEntryFileW(lpszUrlName, 0);
3247c2c66affSColin Finck SetLastError(ERROR_OUTOFMEMORY);
3248c2c66affSColin Finck return NULL;
3249c2c66affSColin Finck }
3250c2c66affSColin Finck
3251c2c66affSColin Finck stream->file = file;
3252c2c66affSColin Finck if(!urlcache_encode_url(lpszUrlName, stream->url, len)) {
3253c2c66affSColin Finck CloseHandle(file);
3254c2c66affSColin Finck UnlockUrlCacheEntryFileW(lpszUrlName, 0);
3255c2c66affSColin Finck heap_free(stream);
3256c2c66affSColin Finck return NULL;
3257c2c66affSColin Finck }
3258c2c66affSColin Finck return stream;
3259c2c66affSColin Finck }
3260c2c66affSColin Finck
3261c2c66affSColin Finck /***********************************************************************
3262c2c66affSColin Finck * UnlockUrlCacheEntryStream (WININET.@)
3263c2c66affSColin Finck *
3264c2c66affSColin Finck */
UnlockUrlCacheEntryStream(IN HANDLE hUrlCacheStream,IN DWORD dwReserved)3265c2c66affSColin Finck BOOL WINAPI UnlockUrlCacheEntryStream(
3266c2c66affSColin Finck IN HANDLE hUrlCacheStream,
3267c2c66affSColin Finck IN DWORD dwReserved
3268c2c66affSColin Finck )
3269c2c66affSColin Finck {
3270c2c66affSColin Finck stream_handle *pStream = (stream_handle*)hUrlCacheStream;
3271c2c66affSColin Finck
3272c2c66affSColin Finck if (dwReserved != 0)
3273c2c66affSColin Finck {
3274c2c66affSColin Finck ERR("dwReserved != 0\n");
3275c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
3276c2c66affSColin Finck return FALSE;
3277c2c66affSColin Finck }
3278c2c66affSColin Finck
3279c2c66affSColin Finck if (IsBadReadPtr(pStream, sizeof(*pStream)) || IsBadStringPtrA(pStream->url, INTERNET_MAX_URL_LENGTH))
3280c2c66affSColin Finck {
3281c2c66affSColin Finck SetLastError(ERROR_INVALID_HANDLE);
3282c2c66affSColin Finck return FALSE;
3283c2c66affSColin Finck }
3284c2c66affSColin Finck
3285c2c66affSColin Finck if (!UnlockUrlCacheEntryFileA(pStream->url, 0))
3286c2c66affSColin Finck return FALSE;
3287c2c66affSColin Finck
3288c2c66affSColin Finck CloseHandle(pStream->file);
3289c2c66affSColin Finck heap_free(pStream);
3290c2c66affSColin Finck return TRUE;
3291c2c66affSColin Finck }
3292c2c66affSColin Finck
3293c2c66affSColin Finck
3294c2c66affSColin Finck /***********************************************************************
3295c2c66affSColin Finck * DeleteUrlCacheEntryA (WININET.@)
3296c2c66affSColin Finck *
3297c2c66affSColin Finck */
DeleteUrlCacheEntryA(LPCSTR lpszUrlName)3298c2c66affSColin Finck BOOL WINAPI DeleteUrlCacheEntryA(LPCSTR lpszUrlName)
3299c2c66affSColin Finck {
3300c2c66affSColin Finck cache_container *pContainer;
3301c2c66affSColin Finck urlcache_header *pHeader;
3302c2c66affSColin Finck struct hash_entry *pHashEntry;
3303c2c66affSColin Finck DWORD error;
3304c2c66affSColin Finck BOOL ret;
3305c2c66affSColin Finck
3306c2c66affSColin Finck TRACE("(%s)\n", debugstr_a(lpszUrlName));
3307c2c66affSColin Finck
3308c2c66affSColin Finck error = cache_containers_find(lpszUrlName, &pContainer);
3309c2c66affSColin Finck if (error != ERROR_SUCCESS)
3310c2c66affSColin Finck {
3311c2c66affSColin Finck SetLastError(error);
3312c2c66affSColin Finck return FALSE;
3313c2c66affSColin Finck }
3314c2c66affSColin Finck
3315c2c66affSColin Finck error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
3316c2c66affSColin Finck if (error != ERROR_SUCCESS)
3317c2c66affSColin Finck {
3318c2c66affSColin Finck SetLastError(error);
3319c2c66affSColin Finck return FALSE;
3320c2c66affSColin Finck }
3321c2c66affSColin Finck
3322c2c66affSColin Finck if (!(pHeader = cache_container_lock_index(pContainer)))
3323c2c66affSColin Finck return FALSE;
3324c2c66affSColin Finck
3325c2c66affSColin Finck if (!urlcache_find_hash_entry(pHeader, lpszUrlName, &pHashEntry))
3326c2c66affSColin Finck {
3327c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
3328c2c66affSColin Finck TRACE("entry %s not found!\n", debugstr_a(lpszUrlName));
3329c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
3330c2c66affSColin Finck return FALSE;
3331c2c66affSColin Finck }
3332c2c66affSColin Finck
3333c2c66affSColin Finck ret = urlcache_entry_delete(pContainer, pHeader, pHashEntry);
3334c2c66affSColin Finck
3335c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
3336c2c66affSColin Finck
3337c2c66affSColin Finck return ret;
3338c2c66affSColin Finck }
3339c2c66affSColin Finck
3340c2c66affSColin Finck /***********************************************************************
3341c2c66affSColin Finck * DeleteUrlCacheEntryW (WININET.@)
3342c2c66affSColin Finck *
3343c2c66affSColin Finck */
DeleteUrlCacheEntryW(LPCWSTR lpszUrlName)3344c2c66affSColin Finck BOOL WINAPI DeleteUrlCacheEntryW(LPCWSTR lpszUrlName)
3345c2c66affSColin Finck {
3346c2c66affSColin Finck char *url;
3347c2c66affSColin Finck BOOL ret;
3348c2c66affSColin Finck
3349c2c66affSColin Finck if(!urlcache_encode_url_alloc(lpszUrlName, &url))
3350c2c66affSColin Finck return FALSE;
3351c2c66affSColin Finck
3352c2c66affSColin Finck ret = DeleteUrlCacheEntryA(url);
3353c2c66affSColin Finck heap_free(url);
3354c2c66affSColin Finck return ret;
3355c2c66affSColin Finck }
3356c2c66affSColin Finck
DeleteUrlCacheContainerA(DWORD d1,DWORD d2)3357c2c66affSColin Finck BOOL WINAPI DeleteUrlCacheContainerA(DWORD d1, DWORD d2)
3358c2c66affSColin Finck {
3359c2c66affSColin Finck FIXME("(0x%08x, 0x%08x) stub\n", d1, d2);
3360c2c66affSColin Finck return TRUE;
3361c2c66affSColin Finck }
3362c2c66affSColin Finck
DeleteUrlCacheContainerW(DWORD d1,DWORD d2)3363c2c66affSColin Finck BOOL WINAPI DeleteUrlCacheContainerW(DWORD d1, DWORD d2)
3364c2c66affSColin Finck {
3365c2c66affSColin Finck FIXME("(0x%08x, 0x%08x) stub\n", d1, d2);
3366c2c66affSColin Finck return TRUE;
3367c2c66affSColin Finck }
3368c2c66affSColin Finck
3369c2c66affSColin Finck /***********************************************************************
3370c2c66affSColin Finck * CreateCacheContainerA (WININET.@)
3371c2c66affSColin Finck */
CreateUrlCacheContainerA(DWORD d1,DWORD d2,DWORD d3,DWORD d4,DWORD d5,DWORD d6,DWORD d7,DWORD d8)3372c2c66affSColin Finck BOOL WINAPI CreateUrlCacheContainerA(DWORD d1, DWORD d2, DWORD d3, DWORD d4,
3373c2c66affSColin Finck DWORD d5, DWORD d6, DWORD d7, DWORD d8)
3374c2c66affSColin Finck {
3375c2c66affSColin Finck FIXME("(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x) stub\n",
3376c2c66affSColin Finck d1, d2, d3, d4, d5, d6, d7, d8);
3377c2c66affSColin Finck return TRUE;
3378c2c66affSColin Finck }
3379c2c66affSColin Finck
3380c2c66affSColin Finck /***********************************************************************
3381c2c66affSColin Finck * CreateCacheContainerW (WININET.@)
3382c2c66affSColin Finck */
CreateUrlCacheContainerW(DWORD d1,DWORD d2,DWORD d3,DWORD d4,DWORD d5,DWORD d6,DWORD d7,DWORD d8)3383c2c66affSColin Finck BOOL WINAPI CreateUrlCacheContainerW(DWORD d1, DWORD d2, DWORD d3, DWORD d4,
3384c2c66affSColin Finck DWORD d5, DWORD d6, DWORD d7, DWORD d8)
3385c2c66affSColin Finck {
3386c2c66affSColin Finck FIXME("(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x) stub\n",
3387c2c66affSColin Finck d1, d2, d3, d4, d5, d6, d7, d8);
3388c2c66affSColin Finck return TRUE;
3389c2c66affSColin Finck }
3390c2c66affSColin Finck
3391c2c66affSColin Finck /***********************************************************************
3392c2c66affSColin Finck * FindFirstUrlCacheContainerA (WININET.@)
3393c2c66affSColin Finck */
FindFirstUrlCacheContainerA(LPVOID p1,LPVOID p2,LPVOID p3,DWORD d1)3394c2c66affSColin Finck HANDLE WINAPI FindFirstUrlCacheContainerA( LPVOID p1, LPVOID p2, LPVOID p3, DWORD d1 )
3395c2c66affSColin Finck {
3396c2c66affSColin Finck FIXME("(%p, %p, %p, 0x%08x) stub\n", p1, p2, p3, d1 );
3397c2c66affSColin Finck return NULL;
3398c2c66affSColin Finck }
3399c2c66affSColin Finck
3400c2c66affSColin Finck /***********************************************************************
3401c2c66affSColin Finck * FindFirstUrlCacheContainerW (WININET.@)
3402c2c66affSColin Finck */
FindFirstUrlCacheContainerW(LPVOID p1,LPVOID p2,LPVOID p3,DWORD d1)3403c2c66affSColin Finck HANDLE WINAPI FindFirstUrlCacheContainerW( LPVOID p1, LPVOID p2, LPVOID p3, DWORD d1 )
3404c2c66affSColin Finck {
3405c2c66affSColin Finck FIXME("(%p, %p, %p, 0x%08x) stub\n", p1, p2, p3, d1 );
3406c2c66affSColin Finck return NULL;
3407c2c66affSColin Finck }
3408c2c66affSColin Finck
3409c2c66affSColin Finck /***********************************************************************
3410c2c66affSColin Finck * FindNextUrlCacheContainerA (WININET.@)
3411c2c66affSColin Finck */
FindNextUrlCacheContainerA(HANDLE handle,LPVOID p1,LPVOID p2)3412c2c66affSColin Finck BOOL WINAPI FindNextUrlCacheContainerA( HANDLE handle, LPVOID p1, LPVOID p2 )
3413c2c66affSColin Finck {
3414c2c66affSColin Finck FIXME("(%p, %p, %p) stub\n", handle, p1, p2 );
3415c2c66affSColin Finck return FALSE;
3416c2c66affSColin Finck }
3417c2c66affSColin Finck
3418c2c66affSColin Finck /***********************************************************************
3419c2c66affSColin Finck * FindNextUrlCacheContainerW (WININET.@)
3420c2c66affSColin Finck */
FindNextUrlCacheContainerW(HANDLE handle,LPVOID p1,LPVOID p2)3421c2c66affSColin Finck BOOL WINAPI FindNextUrlCacheContainerW( HANDLE handle, LPVOID p1, LPVOID p2 )
3422c2c66affSColin Finck {
3423c2c66affSColin Finck FIXME("(%p, %p, %p) stub\n", handle, p1, p2 );
3424c2c66affSColin Finck return FALSE;
3425c2c66affSColin Finck }
3426c2c66affSColin Finck
FindFirstUrlCacheEntryExA(LPCSTR lpszUrlSearchPattern,DWORD dwFlags,DWORD dwFilter,GROUPID GroupId,LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo,LPDWORD lpdwFirstCacheEntryInfoBufferSize,LPVOID lpReserved,LPDWORD pcbReserved2,LPVOID lpReserved3)3427c2c66affSColin Finck HANDLE WINAPI FindFirstUrlCacheEntryExA(
3428c2c66affSColin Finck LPCSTR lpszUrlSearchPattern,
3429c2c66affSColin Finck DWORD dwFlags,
3430c2c66affSColin Finck DWORD dwFilter,
3431c2c66affSColin Finck GROUPID GroupId,
3432c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo,
3433c2c66affSColin Finck LPDWORD lpdwFirstCacheEntryInfoBufferSize,
3434c2c66affSColin Finck LPVOID lpReserved,
3435c2c66affSColin Finck LPDWORD pcbReserved2,
3436c2c66affSColin Finck LPVOID lpReserved3
3437c2c66affSColin Finck )
3438c2c66affSColin Finck {
3439c2c66affSColin Finck FIXME("(%s, 0x%08x, 0x%08x, 0x%s, %p, %p, %p, %p, %p) stub\n", debugstr_a(lpszUrlSearchPattern),
3440c2c66affSColin Finck dwFlags, dwFilter, wine_dbgstr_longlong(GroupId), lpFirstCacheEntryInfo,
3441c2c66affSColin Finck lpdwFirstCacheEntryInfoBufferSize, lpReserved, pcbReserved2,lpReserved3);
3442c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
3443c2c66affSColin Finck return NULL;
3444c2c66affSColin Finck }
3445c2c66affSColin Finck
FindFirstUrlCacheEntryExW(LPCWSTR lpszUrlSearchPattern,DWORD dwFlags,DWORD dwFilter,GROUPID GroupId,LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo,LPDWORD lpdwFirstCacheEntryInfoBufferSize,LPVOID lpReserved,LPDWORD pcbReserved2,LPVOID lpReserved3)3446c2c66affSColin Finck HANDLE WINAPI FindFirstUrlCacheEntryExW(
3447c2c66affSColin Finck LPCWSTR lpszUrlSearchPattern,
3448c2c66affSColin Finck DWORD dwFlags,
3449c2c66affSColin Finck DWORD dwFilter,
3450c2c66affSColin Finck GROUPID GroupId,
3451c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo,
3452c2c66affSColin Finck LPDWORD lpdwFirstCacheEntryInfoBufferSize,
3453c2c66affSColin Finck LPVOID lpReserved,
3454c2c66affSColin Finck LPDWORD pcbReserved2,
3455c2c66affSColin Finck LPVOID lpReserved3
3456c2c66affSColin Finck )
3457c2c66affSColin Finck {
3458c2c66affSColin Finck FIXME("(%s, 0x%08x, 0x%08x, 0x%s, %p, %p, %p, %p, %p) stub\n", debugstr_w(lpszUrlSearchPattern),
3459c2c66affSColin Finck dwFlags, dwFilter, wine_dbgstr_longlong(GroupId), lpFirstCacheEntryInfo,
3460c2c66affSColin Finck lpdwFirstCacheEntryInfoBufferSize, lpReserved, pcbReserved2,lpReserved3);
3461c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
3462c2c66affSColin Finck return NULL;
3463c2c66affSColin Finck }
3464c2c66affSColin Finck
3465c2c66affSColin Finck /***********************************************************************
3466c2c66affSColin Finck * FindFirstUrlCacheEntryA (WININET.@)
3467c2c66affSColin Finck *
3468c2c66affSColin Finck */
FindFirstUrlCacheEntryA(LPCSTR lpszUrlSearchPattern,LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo,LPDWORD lpdwFirstCacheEntryInfoBufferSize)3469c2c66affSColin Finck INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryA(LPCSTR lpszUrlSearchPattern,
3470c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo, LPDWORD lpdwFirstCacheEntryInfoBufferSize)
3471c2c66affSColin Finck {
3472c2c66affSColin Finck find_handle *pEntryHandle;
3473c2c66affSColin Finck
3474c2c66affSColin Finck TRACE("(%s, %p, %p)\n", debugstr_a(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize);
3475c2c66affSColin Finck
3476c2c66affSColin Finck pEntryHandle = heap_alloc(sizeof(*pEntryHandle));
3477c2c66affSColin Finck if (!pEntryHandle)
3478c2c66affSColin Finck return NULL;
3479c2c66affSColin Finck
3480c2c66affSColin Finck pEntryHandle->magic = URLCACHE_FIND_ENTRY_HANDLE_MAGIC;
3481c2c66affSColin Finck if (lpszUrlSearchPattern)
3482c2c66affSColin Finck {
3483c2c66affSColin Finck pEntryHandle->url_search_pattern = heap_strdupA(lpszUrlSearchPattern);
3484c2c66affSColin Finck if (!pEntryHandle->url_search_pattern)
3485c2c66affSColin Finck {
3486c2c66affSColin Finck heap_free(pEntryHandle);
3487c2c66affSColin Finck return NULL;
3488c2c66affSColin Finck }
3489c2c66affSColin Finck }
3490c2c66affSColin Finck else
3491c2c66affSColin Finck pEntryHandle->url_search_pattern = NULL;
3492c2c66affSColin Finck pEntryHandle->container_idx = 0;
3493c2c66affSColin Finck pEntryHandle->hash_table_idx = 0;
3494c2c66affSColin Finck pEntryHandle->hash_entry_idx = 0;
3495c2c66affSColin Finck
3496c2c66affSColin Finck if (!FindNextUrlCacheEntryA(pEntryHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize))
3497c2c66affSColin Finck {
3498c2c66affSColin Finck heap_free(pEntryHandle);
3499c2c66affSColin Finck return NULL;
3500c2c66affSColin Finck }
3501c2c66affSColin Finck return pEntryHandle;
3502c2c66affSColin Finck }
3503c2c66affSColin Finck
3504c2c66affSColin Finck /***********************************************************************
3505c2c66affSColin Finck * FindFirstUrlCacheEntryW (WININET.@)
3506c2c66affSColin Finck *
3507c2c66affSColin Finck */
FindFirstUrlCacheEntryW(LPCWSTR lpszUrlSearchPattern,LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo,LPDWORD lpdwFirstCacheEntryInfoBufferSize)3508c2c66affSColin Finck INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryW(LPCWSTR lpszUrlSearchPattern,
3509c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo, LPDWORD lpdwFirstCacheEntryInfoBufferSize)
3510c2c66affSColin Finck {
3511c2c66affSColin Finck find_handle *pEntryHandle;
3512c2c66affSColin Finck
3513c2c66affSColin Finck TRACE("(%s, %p, %p)\n", debugstr_w(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize);
3514c2c66affSColin Finck
3515c2c66affSColin Finck pEntryHandle = heap_alloc(sizeof(*pEntryHandle));
3516c2c66affSColin Finck if (!pEntryHandle)
3517c2c66affSColin Finck return NULL;
3518c2c66affSColin Finck
3519c2c66affSColin Finck pEntryHandle->magic = URLCACHE_FIND_ENTRY_HANDLE_MAGIC;
3520c2c66affSColin Finck if (lpszUrlSearchPattern)
3521c2c66affSColin Finck {
3522c2c66affSColin Finck pEntryHandle->url_search_pattern = heap_strdupWtoA(lpszUrlSearchPattern);
3523c2c66affSColin Finck if (!pEntryHandle->url_search_pattern)
3524c2c66affSColin Finck {
3525c2c66affSColin Finck heap_free(pEntryHandle);
3526c2c66affSColin Finck return NULL;
3527c2c66affSColin Finck }
3528c2c66affSColin Finck }
3529c2c66affSColin Finck else
3530c2c66affSColin Finck pEntryHandle->url_search_pattern = NULL;
3531c2c66affSColin Finck pEntryHandle->container_idx = 0;
3532c2c66affSColin Finck pEntryHandle->hash_table_idx = 0;
3533c2c66affSColin Finck pEntryHandle->hash_entry_idx = 0;
3534c2c66affSColin Finck
3535c2c66affSColin Finck if (!FindNextUrlCacheEntryW(pEntryHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize))
3536c2c66affSColin Finck {
3537c2c66affSColin Finck heap_free(pEntryHandle);
3538c2c66affSColin Finck return NULL;
3539c2c66affSColin Finck }
3540c2c66affSColin Finck return pEntryHandle;
3541c2c66affSColin Finck }
3542c2c66affSColin Finck
urlcache_find_next_entry(HANDLE hEnumHandle,LPINTERNET_CACHE_ENTRY_INFOA lpNextCacheEntryInfo,LPDWORD lpdwNextCacheEntryInfoBufferSize,BOOL unicode)3543c2c66affSColin Finck static BOOL urlcache_find_next_entry(
3544c2c66affSColin Finck HANDLE hEnumHandle,
3545c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOA lpNextCacheEntryInfo,
3546c2c66affSColin Finck LPDWORD lpdwNextCacheEntryInfoBufferSize,
3547c2c66affSColin Finck BOOL unicode)
3548c2c66affSColin Finck {
3549c2c66affSColin Finck find_handle *pEntryHandle = (find_handle*)hEnumHandle;
3550c2c66affSColin Finck cache_container *pContainer;
3551c2c66affSColin Finck
3552c2c66affSColin Finck if (pEntryHandle->magic != URLCACHE_FIND_ENTRY_HANDLE_MAGIC)
3553c2c66affSColin Finck {
3554c2c66affSColin Finck SetLastError(ERROR_INVALID_HANDLE);
3555c2c66affSColin Finck return FALSE;
3556c2c66affSColin Finck }
3557c2c66affSColin Finck
3558c2c66affSColin Finck for (; cache_containers_enum(pEntryHandle->url_search_pattern, pEntryHandle->container_idx, &pContainer);
3559c2c66affSColin Finck pEntryHandle->container_idx++, pEntryHandle->hash_table_idx = 0)
3560c2c66affSColin Finck {
3561c2c66affSColin Finck urlcache_header *pHeader;
3562c2c66affSColin Finck entry_hash_table *pHashTableEntry;
3563c2c66affSColin Finck DWORD error;
3564c2c66affSColin Finck
3565c2c66affSColin Finck error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
3566c2c66affSColin Finck if (error != ERROR_SUCCESS)
3567c2c66affSColin Finck {
3568c2c66affSColin Finck SetLastError(error);
3569c2c66affSColin Finck return FALSE;
3570c2c66affSColin Finck }
3571c2c66affSColin Finck
3572c2c66affSColin Finck if (!(pHeader = cache_container_lock_index(pContainer)))
3573c2c66affSColin Finck return FALSE;
3574c2c66affSColin Finck
3575c2c66affSColin Finck for (; urlcache_enum_hash_tables(pHeader, &pEntryHandle->hash_table_idx, &pHashTableEntry);
3576c2c66affSColin Finck pEntryHandle->hash_table_idx++, pEntryHandle->hash_entry_idx = 0)
3577c2c66affSColin Finck {
3578c2c66affSColin Finck const struct hash_entry *pHashEntry = NULL;
3579c2c66affSColin Finck for (; urlcache_enum_hash_table_entries(pHeader, pHashTableEntry, &pEntryHandle->hash_entry_idx, &pHashEntry);
3580c2c66affSColin Finck pEntryHandle->hash_entry_idx++)
3581c2c66affSColin Finck {
3582c2c66affSColin Finck const entry_url *pUrlEntry;
3583c2c66affSColin Finck const entry_header *pEntry = (const entry_header*)((LPBYTE)pHeader + pHashEntry->offset);
3584c2c66affSColin Finck
3585c2c66affSColin Finck if (pEntry->signature != URL_SIGNATURE)
3586c2c66affSColin Finck continue;
3587c2c66affSColin Finck
3588c2c66affSColin Finck pUrlEntry = (const entry_url *)pEntry;
3589c2c66affSColin Finck TRACE("Found URL: %s\n",
3590c2c66affSColin Finck debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->url_off));
3591c2c66affSColin Finck TRACE("Header info: %s\n",
3592c2c66affSColin Finck debugstr_an((LPCSTR)pUrlEntry + pUrlEntry->header_info_off,
3593c2c66affSColin Finck pUrlEntry->header_info_size));
3594c2c66affSColin Finck
3595c2c66affSColin Finck error = urlcache_copy_entry(
3596c2c66affSColin Finck pContainer,
3597c2c66affSColin Finck pHeader,
3598c2c66affSColin Finck lpNextCacheEntryInfo,
3599c2c66affSColin Finck lpdwNextCacheEntryInfoBufferSize,
3600c2c66affSColin Finck pUrlEntry,
3601c2c66affSColin Finck unicode);
3602c2c66affSColin Finck if (error != ERROR_SUCCESS)
3603c2c66affSColin Finck {
3604c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
3605c2c66affSColin Finck SetLastError(error);
3606c2c66affSColin Finck return FALSE;
3607c2c66affSColin Finck }
3608c2c66affSColin Finck if(pUrlEntry->local_name_off)
3609c2c66affSColin Finck TRACE("Local File Name: %s\n", debugstr_a((LPCSTR)pUrlEntry + pUrlEntry->local_name_off));
3610c2c66affSColin Finck
3611c2c66affSColin Finck /* increment the current index so that next time the function
3612c2c66affSColin Finck * is called the next entry is returned */
3613c2c66affSColin Finck pEntryHandle->hash_entry_idx++;
3614c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
3615c2c66affSColin Finck return TRUE;
3616c2c66affSColin Finck }
3617c2c66affSColin Finck }
3618c2c66affSColin Finck
3619c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
3620c2c66affSColin Finck }
3621c2c66affSColin Finck
3622c2c66affSColin Finck SetLastError(ERROR_NO_MORE_ITEMS);
3623c2c66affSColin Finck return FALSE;
3624c2c66affSColin Finck }
3625c2c66affSColin Finck
3626c2c66affSColin Finck /***********************************************************************
3627c2c66affSColin Finck * FindNextUrlCacheEntryA (WININET.@)
3628c2c66affSColin Finck */
FindNextUrlCacheEntryA(HANDLE hEnumHandle,LPINTERNET_CACHE_ENTRY_INFOA lpNextCacheEntryInfo,LPDWORD lpdwNextCacheEntryInfoBufferSize)3629c2c66affSColin Finck BOOL WINAPI FindNextUrlCacheEntryA(
3630c2c66affSColin Finck HANDLE hEnumHandle,
3631c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOA lpNextCacheEntryInfo,
3632c2c66affSColin Finck LPDWORD lpdwNextCacheEntryInfoBufferSize)
3633c2c66affSColin Finck {
3634c2c66affSColin Finck TRACE("(%p, %p, %p)\n", hEnumHandle, lpNextCacheEntryInfo, lpdwNextCacheEntryInfoBufferSize);
3635c2c66affSColin Finck
3636c2c66affSColin Finck return urlcache_find_next_entry(hEnumHandle, lpNextCacheEntryInfo,
3637c2c66affSColin Finck lpdwNextCacheEntryInfoBufferSize, FALSE /* not UNICODE */);
3638c2c66affSColin Finck }
3639c2c66affSColin Finck
3640c2c66affSColin Finck /***********************************************************************
3641c2c66affSColin Finck * FindNextUrlCacheEntryW (WININET.@)
3642c2c66affSColin Finck */
FindNextUrlCacheEntryW(HANDLE hEnumHandle,LPINTERNET_CACHE_ENTRY_INFOW lpNextCacheEntryInfo,LPDWORD lpdwNextCacheEntryInfoBufferSize)3643c2c66affSColin Finck BOOL WINAPI FindNextUrlCacheEntryW(
3644c2c66affSColin Finck HANDLE hEnumHandle,
3645c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW lpNextCacheEntryInfo,
3646c2c66affSColin Finck LPDWORD lpdwNextCacheEntryInfoBufferSize
3647c2c66affSColin Finck )
3648c2c66affSColin Finck {
3649c2c66affSColin Finck TRACE("(%p, %p, %p)\n", hEnumHandle, lpNextCacheEntryInfo, lpdwNextCacheEntryInfoBufferSize);
3650c2c66affSColin Finck
3651c2c66affSColin Finck return urlcache_find_next_entry(hEnumHandle,
3652c2c66affSColin Finck (LPINTERNET_CACHE_ENTRY_INFOA)lpNextCacheEntryInfo,
3653c2c66affSColin Finck lpdwNextCacheEntryInfoBufferSize, TRUE /* UNICODE */);
3654c2c66affSColin Finck }
3655c2c66affSColin Finck
3656c2c66affSColin Finck /***********************************************************************
3657c2c66affSColin Finck * FindCloseUrlCache (WININET.@)
3658c2c66affSColin Finck */
FindCloseUrlCache(HANDLE hEnumHandle)3659c2c66affSColin Finck BOOL WINAPI FindCloseUrlCache(HANDLE hEnumHandle)
3660c2c66affSColin Finck {
3661c2c66affSColin Finck find_handle *pEntryHandle = (find_handle*)hEnumHandle;
3662c2c66affSColin Finck
3663c2c66affSColin Finck TRACE("(%p)\n", hEnumHandle);
3664c2c66affSColin Finck
3665c2c66affSColin Finck if (!pEntryHandle || pEntryHandle->magic != URLCACHE_FIND_ENTRY_HANDLE_MAGIC)
3666c2c66affSColin Finck {
3667c2c66affSColin Finck SetLastError(ERROR_INVALID_HANDLE);
3668c2c66affSColin Finck return FALSE;
3669c2c66affSColin Finck }
3670c2c66affSColin Finck
3671c2c66affSColin Finck pEntryHandle->magic = 0;
3672c2c66affSColin Finck heap_free(pEntryHandle->url_search_pattern);
3673c2c66affSColin Finck heap_free(pEntryHandle);
3674c2c66affSColin Finck return TRUE;
3675c2c66affSColin Finck }
3676c2c66affSColin Finck
FindFirstUrlCacheGroup(DWORD dwFlags,DWORD dwFilter,LPVOID lpSearchCondition,DWORD dwSearchCondition,GROUPID * lpGroupId,LPVOID lpReserved)3677c2c66affSColin Finck HANDLE WINAPI FindFirstUrlCacheGroup( DWORD dwFlags, DWORD dwFilter, LPVOID lpSearchCondition,
3678c2c66affSColin Finck DWORD dwSearchCondition, GROUPID* lpGroupId, LPVOID lpReserved )
3679c2c66affSColin Finck {
3680c2c66affSColin Finck FIXME("(0x%08x, 0x%08x, %p, 0x%08x, %p, %p) stub\n", dwFlags, dwFilter, lpSearchCondition,
3681c2c66affSColin Finck dwSearchCondition, lpGroupId, lpReserved);
3682c2c66affSColin Finck return NULL;
3683c2c66affSColin Finck }
3684c2c66affSColin Finck
FindNextUrlCacheEntryExA(HANDLE hEnumHandle,LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo,LPDWORD lpdwFirstCacheEntryInfoBufferSize,LPVOID lpReserved,LPDWORD pcbReserved2,LPVOID lpReserved3)3685c2c66affSColin Finck BOOL WINAPI FindNextUrlCacheEntryExA(
3686c2c66affSColin Finck HANDLE hEnumHandle,
3687c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo,
3688c2c66affSColin Finck LPDWORD lpdwFirstCacheEntryInfoBufferSize,
3689c2c66affSColin Finck LPVOID lpReserved,
3690c2c66affSColin Finck LPDWORD pcbReserved2,
3691c2c66affSColin Finck LPVOID lpReserved3
3692c2c66affSColin Finck )
3693c2c66affSColin Finck {
3694c2c66affSColin Finck FIXME("(%p, %p, %p, %p, %p, %p) stub\n", hEnumHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize,
3695c2c66affSColin Finck lpReserved, pcbReserved2, lpReserved3);
3696c2c66affSColin Finck return FALSE;
3697c2c66affSColin Finck }
3698c2c66affSColin Finck
FindNextUrlCacheEntryExW(HANDLE hEnumHandle,LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo,LPDWORD lpdwFirstCacheEntryInfoBufferSize,LPVOID lpReserved,LPDWORD pcbReserved2,LPVOID lpReserved3)3699c2c66affSColin Finck BOOL WINAPI FindNextUrlCacheEntryExW(
3700c2c66affSColin Finck HANDLE hEnumHandle,
3701c2c66affSColin Finck LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo,
3702c2c66affSColin Finck LPDWORD lpdwFirstCacheEntryInfoBufferSize,
3703c2c66affSColin Finck LPVOID lpReserved,
3704c2c66affSColin Finck LPDWORD pcbReserved2,
3705c2c66affSColin Finck LPVOID lpReserved3
3706c2c66affSColin Finck )
3707c2c66affSColin Finck {
3708c2c66affSColin Finck FIXME("(%p, %p, %p, %p, %p, %p) stub\n", hEnumHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize,
3709c2c66affSColin Finck lpReserved, pcbReserved2, lpReserved3);
3710c2c66affSColin Finck return FALSE;
3711c2c66affSColin Finck }
3712c2c66affSColin Finck
FindNextUrlCacheGroup(HANDLE hFind,GROUPID * lpGroupId,LPVOID lpReserved)3713c2c66affSColin Finck BOOL WINAPI FindNextUrlCacheGroup( HANDLE hFind, GROUPID* lpGroupId, LPVOID lpReserved )
3714c2c66affSColin Finck {
3715c2c66affSColin Finck FIXME("(%p, %p, %p) stub\n", hFind, lpGroupId, lpReserved);
3716c2c66affSColin Finck return FALSE;
3717c2c66affSColin Finck }
3718c2c66affSColin Finck
3719c2c66affSColin Finck /***********************************************************************
3720c2c66affSColin Finck * CreateUrlCacheGroup (WININET.@)
3721c2c66affSColin Finck *
3722c2c66affSColin Finck */
CreateUrlCacheGroup(DWORD dwFlags,LPVOID lpReserved)3723c2c66affSColin Finck INTERNETAPI GROUPID WINAPI CreateUrlCacheGroup(DWORD dwFlags, LPVOID lpReserved)
3724c2c66affSColin Finck {
3725c2c66affSColin Finck FIXME("(0x%08x, %p): stub\n", dwFlags, lpReserved);
3726c2c66affSColin Finck return FALSE;
3727c2c66affSColin Finck }
3728c2c66affSColin Finck
3729c2c66affSColin Finck /***********************************************************************
3730c2c66affSColin Finck * DeleteUrlCacheGroup (WININET.@)
3731c2c66affSColin Finck *
3732c2c66affSColin Finck */
DeleteUrlCacheGroup(GROUPID GroupId,DWORD dwFlags,LPVOID lpReserved)3733c2c66affSColin Finck BOOL WINAPI DeleteUrlCacheGroup(GROUPID GroupId, DWORD dwFlags, LPVOID lpReserved)
3734c2c66affSColin Finck {
3735c2c66affSColin Finck FIXME("(0x%s, 0x%08x, %p) stub\n",
3736c2c66affSColin Finck wine_dbgstr_longlong(GroupId), dwFlags, lpReserved);
3737c2c66affSColin Finck return FALSE;
3738c2c66affSColin Finck }
3739c2c66affSColin Finck
3740c2c66affSColin Finck /***********************************************************************
3741c2c66affSColin Finck * DeleteWpadCacheForNetworks (WININET.@)
3742c2c66affSColin Finck * Undocumented, added in IE8
3743c2c66affSColin Finck */
DeleteWpadCacheForNetworks(DWORD unk1)3744c2c66affSColin Finck BOOL WINAPI DeleteWpadCacheForNetworks(DWORD unk1)
3745c2c66affSColin Finck {
3746c2c66affSColin Finck FIXME("(%d) stub\n", unk1);
3747c2c66affSColin Finck return FALSE;
3748c2c66affSColin Finck }
3749c2c66affSColin Finck
3750c2c66affSColin Finck /***********************************************************************
3751c2c66affSColin Finck * SetUrlCacheEntryGroupA (WININET.@)
3752c2c66affSColin Finck *
3753c2c66affSColin Finck */
SetUrlCacheEntryGroupA(LPCSTR lpszUrlName,DWORD dwFlags,GROUPID GroupId,LPBYTE pbGroupAttributes,DWORD cbGroupAttributes,LPVOID lpReserved)3754c2c66affSColin Finck BOOL WINAPI SetUrlCacheEntryGroupA(LPCSTR lpszUrlName, DWORD dwFlags,
3755c2c66affSColin Finck GROUPID GroupId, LPBYTE pbGroupAttributes, DWORD cbGroupAttributes,
3756c2c66affSColin Finck LPVOID lpReserved)
3757c2c66affSColin Finck {
3758c2c66affSColin Finck FIXME("(%s, 0x%08x, 0x%s, %p, 0x%08x, %p) stub\n",
3759c2c66affSColin Finck debugstr_a(lpszUrlName), dwFlags, wine_dbgstr_longlong(GroupId),
3760c2c66affSColin Finck pbGroupAttributes, cbGroupAttributes, lpReserved);
3761c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
3762c2c66affSColin Finck return FALSE;
3763c2c66affSColin Finck }
3764c2c66affSColin Finck
3765c2c66affSColin Finck /***********************************************************************
3766c2c66affSColin Finck * SetUrlCacheEntryGroupW (WININET.@)
3767c2c66affSColin Finck *
3768c2c66affSColin Finck */
SetUrlCacheEntryGroupW(LPCWSTR lpszUrlName,DWORD dwFlags,GROUPID GroupId,LPBYTE pbGroupAttributes,DWORD cbGroupAttributes,LPVOID lpReserved)3769c2c66affSColin Finck BOOL WINAPI SetUrlCacheEntryGroupW(LPCWSTR lpszUrlName, DWORD dwFlags,
3770c2c66affSColin Finck GROUPID GroupId, LPBYTE pbGroupAttributes, DWORD cbGroupAttributes,
3771c2c66affSColin Finck LPVOID lpReserved)
3772c2c66affSColin Finck {
3773c2c66affSColin Finck FIXME("(%s, 0x%08x, 0x%s, %p, 0x%08x, %p) stub\n",
3774c2c66affSColin Finck debugstr_w(lpszUrlName), dwFlags, wine_dbgstr_longlong(GroupId),
3775c2c66affSColin Finck pbGroupAttributes, cbGroupAttributes, lpReserved);
3776c2c66affSColin Finck SetLastError(ERROR_FILE_NOT_FOUND);
3777c2c66affSColin Finck return FALSE;
3778c2c66affSColin Finck }
3779c2c66affSColin Finck
find_container(DWORD flags)3780c239cdd4SAmine Khaldi static cache_container *find_container(DWORD flags)
3781c239cdd4SAmine Khaldi {
3782c239cdd4SAmine Khaldi cache_container *container;
3783c239cdd4SAmine Khaldi
3784c239cdd4SAmine Khaldi LIST_FOR_EACH_ENTRY(container, &UrlContainers, cache_container, entry)
3785c239cdd4SAmine Khaldi {
3786c239cdd4SAmine Khaldi switch (flags & (CACHE_CONFIG_CONTENT_PATHS_FC | CACHE_CONFIG_COOKIES_PATHS_FC | CACHE_CONFIG_HISTORY_PATHS_FC))
3787c239cdd4SAmine Khaldi {
3788c239cdd4SAmine Khaldi case 0:
3789c239cdd4SAmine Khaldi case CACHE_CONFIG_CONTENT_PATHS_FC:
3790c239cdd4SAmine Khaldi if (container->default_entry_type == NORMAL_CACHE_ENTRY)
3791c239cdd4SAmine Khaldi return container;
3792c239cdd4SAmine Khaldi break;
3793c239cdd4SAmine Khaldi
3794c239cdd4SAmine Khaldi case CACHE_CONFIG_COOKIES_PATHS_FC:
3795c239cdd4SAmine Khaldi if (container->default_entry_type == COOKIE_CACHE_ENTRY)
3796c239cdd4SAmine Khaldi return container;
3797c239cdd4SAmine Khaldi break;
3798c239cdd4SAmine Khaldi
3799c239cdd4SAmine Khaldi case CACHE_CONFIG_HISTORY_PATHS_FC:
3800c239cdd4SAmine Khaldi if (container->default_entry_type == URLHISTORY_CACHE_ENTRY)
3801c239cdd4SAmine Khaldi return container;
3802c239cdd4SAmine Khaldi break;
3803c239cdd4SAmine Khaldi
3804c239cdd4SAmine Khaldi default:
3805c239cdd4SAmine Khaldi FIXME("flags %08x not handled\n", flags);
3806c239cdd4SAmine Khaldi break;
3807c239cdd4SAmine Khaldi }
3808c239cdd4SAmine Khaldi }
3809c239cdd4SAmine Khaldi
3810c239cdd4SAmine Khaldi return NULL;
3811c239cdd4SAmine Khaldi }
3812c239cdd4SAmine Khaldi
3813c2c66affSColin Finck /***********************************************************************
3814c2c66affSColin Finck * GetUrlCacheConfigInfoW (WININET.@)
3815c2c66affSColin Finck */
GetUrlCacheConfigInfoW(LPINTERNET_CACHE_CONFIG_INFOW info,LPDWORD size,DWORD flags)3816c239cdd4SAmine Khaldi BOOL WINAPI GetUrlCacheConfigInfoW(LPINTERNET_CACHE_CONFIG_INFOW info, LPDWORD size, DWORD flags)
3817c2c66affSColin Finck {
3818c239cdd4SAmine Khaldi cache_container *container;
3819c239cdd4SAmine Khaldi DWORD error;
3820c239cdd4SAmine Khaldi
3821c239cdd4SAmine Khaldi FIXME("(%p, %p, %x): semi-stub\n", info, size, flags);
3822c239cdd4SAmine Khaldi
3823c239cdd4SAmine Khaldi if (!info || !(container = find_container(flags)))
3824c239cdd4SAmine Khaldi {
3825c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
3826c2c66affSColin Finck return FALSE;
3827c2c66affSColin Finck }
3828c2c66affSColin Finck
3829c239cdd4SAmine Khaldi error = cache_container_open_index(container, MIN_BLOCK_NO);
3830c239cdd4SAmine Khaldi if (error != ERROR_SUCCESS)
3831c239cdd4SAmine Khaldi {
3832c239cdd4SAmine Khaldi INTERNET_SetLastError(error);
3833c239cdd4SAmine Khaldi return FALSE;
3834c239cdd4SAmine Khaldi }
3835c239cdd4SAmine Khaldi
3836c239cdd4SAmine Khaldi info->dwContainer = 0;
3837c239cdd4SAmine Khaldi info->dwQuota = FILE_SIZE(MAX_BLOCK_NO) / 1024;
3838c239cdd4SAmine Khaldi info->dwReserved4 = 0;
3839c239cdd4SAmine Khaldi info->fPerUser = TRUE;
3840c239cdd4SAmine Khaldi info->dwSyncMode = 0;
3841c239cdd4SAmine Khaldi info->dwNumCachePaths = 1;
3842c239cdd4SAmine Khaldi info->dwNormalUsage = 0;
3843c239cdd4SAmine Khaldi info->dwExemptUsage = 0;
3844c239cdd4SAmine Khaldi info->u.s.dwCacheSize = container->file_size / 1024;
3845c239cdd4SAmine Khaldi lstrcpynW(info->u.s.CachePath, container->path, MAX_PATH);
3846c239cdd4SAmine Khaldi
3847c239cdd4SAmine Khaldi cache_container_close_index(container);
3848c239cdd4SAmine Khaldi
3849c239cdd4SAmine Khaldi TRACE("CachePath %s\n", debugstr_w(info->u.s.CachePath));
3850c239cdd4SAmine Khaldi
3851c239cdd4SAmine Khaldi return TRUE;
3852c239cdd4SAmine Khaldi }
3853c239cdd4SAmine Khaldi
3854c2c66affSColin Finck /***********************************************************************
3855c2c66affSColin Finck * GetUrlCacheConfigInfoA (WININET.@)
3856c2c66affSColin Finck */
GetUrlCacheConfigInfoA(LPINTERNET_CACHE_CONFIG_INFOA info,LPDWORD size,DWORD flags)3857c239cdd4SAmine Khaldi BOOL WINAPI GetUrlCacheConfigInfoA(LPINTERNET_CACHE_CONFIG_INFOA info, LPDWORD size, DWORD flags)
3858c2c66affSColin Finck {
3859c239cdd4SAmine Khaldi INTERNET_CACHE_CONFIG_INFOW infoW;
3860c239cdd4SAmine Khaldi
3861c239cdd4SAmine Khaldi TRACE("(%p, %p, %x)\n", info, size, flags);
3862c239cdd4SAmine Khaldi
3863c239cdd4SAmine Khaldi if (!info)
3864c239cdd4SAmine Khaldi {
3865c2c66affSColin Finck INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
3866c2c66affSColin Finck return FALSE;
3867c2c66affSColin Finck }
3868c2c66affSColin Finck
3869c239cdd4SAmine Khaldi infoW.dwStructSize = sizeof(infoW);
3870c239cdd4SAmine Khaldi if (!GetUrlCacheConfigInfoW(&infoW, size, flags))
3871c239cdd4SAmine Khaldi return FALSE;
3872c239cdd4SAmine Khaldi
3873c239cdd4SAmine Khaldi info->dwContainer = infoW.dwContainer;
3874c239cdd4SAmine Khaldi info->dwQuota = infoW.dwQuota;
3875c239cdd4SAmine Khaldi info->dwReserved4 = infoW.dwReserved4;
3876c239cdd4SAmine Khaldi info->fPerUser = infoW.fPerUser;
3877c239cdd4SAmine Khaldi info->dwSyncMode = infoW.dwSyncMode;
3878c239cdd4SAmine Khaldi info->dwNumCachePaths = infoW.dwNumCachePaths;
3879c239cdd4SAmine Khaldi info->dwNormalUsage = infoW.dwNormalUsage;
3880c239cdd4SAmine Khaldi info->dwExemptUsage = infoW.dwExemptUsage;
3881c239cdd4SAmine Khaldi info->u.s.dwCacheSize = infoW.u.s.dwCacheSize;
3882c239cdd4SAmine Khaldi WideCharToMultiByte(CP_ACP, 0, infoW.u.s.CachePath, -1, info->u.s.CachePath, MAX_PATH, NULL, NULL);
3883c239cdd4SAmine Khaldi
3884c239cdd4SAmine Khaldi return TRUE;
3885c239cdd4SAmine Khaldi }
3886c239cdd4SAmine Khaldi
GetUrlCacheGroupAttributeA(GROUPID gid,DWORD dwFlags,DWORD dwAttributes,LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo,LPDWORD lpdwGroupInfo,LPVOID lpReserved)3887c2c66affSColin Finck BOOL WINAPI GetUrlCacheGroupAttributeA( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
3888c2c66affSColin Finck LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo,
3889c2c66affSColin Finck LPDWORD lpdwGroupInfo, LPVOID lpReserved )
3890c2c66affSColin Finck {
3891c2c66affSColin Finck FIXME("(0x%s, 0x%08x, 0x%08x, %p, %p, %p) stub\n",
3892c2c66affSColin Finck wine_dbgstr_longlong(gid), dwFlags, dwAttributes, lpGroupInfo,
3893c2c66affSColin Finck lpdwGroupInfo, lpReserved);
3894c2c66affSColin Finck return FALSE;
3895c2c66affSColin Finck }
3896c2c66affSColin Finck
GetUrlCacheGroupAttributeW(GROUPID gid,DWORD dwFlags,DWORD dwAttributes,LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo,LPDWORD lpdwGroupInfo,LPVOID lpReserved)3897c2c66affSColin Finck BOOL WINAPI GetUrlCacheGroupAttributeW( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
3898c2c66affSColin Finck LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo,
3899c2c66affSColin Finck LPDWORD lpdwGroupInfo, LPVOID lpReserved )
3900c2c66affSColin Finck {
3901c2c66affSColin Finck FIXME("(0x%s, 0x%08x, 0x%08x, %p, %p, %p) stub\n",
3902c2c66affSColin Finck wine_dbgstr_longlong(gid), dwFlags, dwAttributes, lpGroupInfo,
3903c2c66affSColin Finck lpdwGroupInfo, lpReserved);
3904c2c66affSColin Finck return FALSE;
3905c2c66affSColin Finck }
3906c2c66affSColin Finck
SetUrlCacheGroupAttributeA(GROUPID gid,DWORD dwFlags,DWORD dwAttributes,LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo,LPVOID lpReserved)3907c2c66affSColin Finck BOOL WINAPI SetUrlCacheGroupAttributeA( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
3908c2c66affSColin Finck LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo, LPVOID lpReserved )
3909c2c66affSColin Finck {
3910c2c66affSColin Finck FIXME("(0x%s, 0x%08x, 0x%08x, %p, %p) stub\n",
3911c2c66affSColin Finck wine_dbgstr_longlong(gid), dwFlags, dwAttributes, lpGroupInfo, lpReserved);
3912c2c66affSColin Finck return TRUE;
3913c2c66affSColin Finck }
3914c2c66affSColin Finck
SetUrlCacheGroupAttributeW(GROUPID gid,DWORD dwFlags,DWORD dwAttributes,LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo,LPVOID lpReserved)3915c2c66affSColin Finck BOOL WINAPI SetUrlCacheGroupAttributeW( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
3916c2c66affSColin Finck LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo, LPVOID lpReserved )
3917c2c66affSColin Finck {
3918c2c66affSColin Finck FIXME("(0x%s, 0x%08x, 0x%08x, %p, %p) stub\n",
3919c2c66affSColin Finck wine_dbgstr_longlong(gid), dwFlags, dwAttributes, lpGroupInfo, lpReserved);
3920c2c66affSColin Finck return TRUE;
3921c2c66affSColin Finck }
3922c2c66affSColin Finck
SetUrlCacheConfigInfoA(LPINTERNET_CACHE_CONFIG_INFOA lpCacheConfigInfo,DWORD dwFieldControl)3923c2c66affSColin Finck BOOL WINAPI SetUrlCacheConfigInfoA( LPINTERNET_CACHE_CONFIG_INFOA lpCacheConfigInfo, DWORD dwFieldControl )
3924c2c66affSColin Finck {
3925c2c66affSColin Finck FIXME("(%p, 0x%08x) stub\n", lpCacheConfigInfo, dwFieldControl);
3926c2c66affSColin Finck return TRUE;
3927c2c66affSColin Finck }
3928c2c66affSColin Finck
SetUrlCacheConfigInfoW(LPINTERNET_CACHE_CONFIG_INFOW lpCacheConfigInfo,DWORD dwFieldControl)3929c2c66affSColin Finck BOOL WINAPI SetUrlCacheConfigInfoW( LPINTERNET_CACHE_CONFIG_INFOW lpCacheConfigInfo, DWORD dwFieldControl )
3930c2c66affSColin Finck {
3931c2c66affSColin Finck FIXME("(%p, 0x%08x) stub\n", lpCacheConfigInfo, dwFieldControl);
3932c2c66affSColin Finck return TRUE;
3933c2c66affSColin Finck }
3934c2c66affSColin Finck
3935c2c66affSColin Finck /***********************************************************************
3936c2c66affSColin Finck * DeleteIE3Cache (WININET.@)
3937c2c66affSColin Finck *
3938c2c66affSColin Finck * Deletes the files used by the IE3 URL caching system.
3939c2c66affSColin Finck *
3940c2c66affSColin Finck * PARAMS
3941c2c66affSColin Finck * hWnd [I] A dummy window.
3942c2c66affSColin Finck * hInst [I] Instance of process calling the function.
3943c2c66affSColin Finck * lpszCmdLine [I] Options used by function.
3944c2c66affSColin Finck * nCmdShow [I] The nCmdShow value to use when showing windows created, if any.
3945c2c66affSColin Finck */
DeleteIE3Cache(HWND hWnd,HINSTANCE hInst,LPSTR lpszCmdLine,int nCmdShow)3946c2c66affSColin Finck DWORD WINAPI DeleteIE3Cache(HWND hWnd, HINSTANCE hInst, LPSTR lpszCmdLine, int nCmdShow)
3947c2c66affSColin Finck {
3948c2c66affSColin Finck FIXME("(%p, %p, %s, %d)\n", hWnd, hInst, debugstr_a(lpszCmdLine), nCmdShow);
3949c2c66affSColin Finck return 0;
3950c2c66affSColin Finck }
3951c2c66affSColin Finck
urlcache_entry_is_expired(const entry_url * pUrlEntry,FILETIME * pftLastModified)3952c2c66affSColin Finck static BOOL urlcache_entry_is_expired(const entry_url *pUrlEntry,
3953c2c66affSColin Finck FILETIME *pftLastModified)
3954c2c66affSColin Finck {
3955c2c66affSColin Finck BOOL ret;
3956c2c66affSColin Finck FILETIME now, expired;
3957c2c66affSColin Finck
3958c2c66affSColin Finck *pftLastModified = pUrlEntry->modification_time;
3959c2c66affSColin Finck GetSystemTimeAsFileTime(&now);
3960c2c66affSColin Finck dos_date_time_to_file_time(pUrlEntry->expire_date,
3961c2c66affSColin Finck pUrlEntry->expire_time, &expired);
3962c2c66affSColin Finck /* If the expired time is 0, it's interpreted as not expired */
3963c2c66affSColin Finck if (!expired.dwLowDateTime && !expired.dwHighDateTime)
3964c2c66affSColin Finck ret = FALSE;
3965c2c66affSColin Finck else
3966c2c66affSColin Finck ret = CompareFileTime(&expired, &now) < 0;
3967c2c66affSColin Finck return ret;
3968c2c66affSColin Finck }
3969c2c66affSColin Finck
3970c2c66affSColin Finck /***********************************************************************
3971c2c66affSColin Finck * IsUrlCacheEntryExpiredA (WININET.@)
3972c2c66affSColin Finck *
3973c2c66affSColin Finck * PARAMS
3974c2c66affSColin Finck * url [I] Url
3975c2c66affSColin Finck * dwFlags [I] Unknown
3976c2c66affSColin Finck * pftLastModified [O] Last modified time
3977c2c66affSColin Finck */
IsUrlCacheEntryExpiredA(LPCSTR url,DWORD dwFlags,FILETIME * pftLastModified)3978c2c66affSColin Finck BOOL WINAPI IsUrlCacheEntryExpiredA(LPCSTR url, DWORD dwFlags, FILETIME* pftLastModified)
3979c2c66affSColin Finck {
3980c2c66affSColin Finck urlcache_header *pHeader;
3981c2c66affSColin Finck struct hash_entry *pHashEntry;
3982c2c66affSColin Finck const entry_header *pEntry;
3983c2c66affSColin Finck const entry_url * pUrlEntry;
3984c2c66affSColin Finck cache_container *pContainer;
3985c2c66affSColin Finck BOOL expired;
3986c2c66affSColin Finck
3987c2c66affSColin Finck TRACE("(%s, %08x, %p)\n", debugstr_a(url), dwFlags, pftLastModified);
3988c2c66affSColin Finck
3989c2c66affSColin Finck if (!url || !pftLastModified)
3990c2c66affSColin Finck return TRUE;
3991c2c66affSColin Finck if (dwFlags)
3992c2c66affSColin Finck FIXME("unknown flags 0x%08x\n", dwFlags);
3993c2c66affSColin Finck
3994c2c66affSColin Finck /* Any error implies that the URL is expired, i.e. not in the cache */
3995c2c66affSColin Finck if (cache_containers_find(url, &pContainer))
3996c2c66affSColin Finck {
3997c2c66affSColin Finck memset(pftLastModified, 0, sizeof(*pftLastModified));
3998c2c66affSColin Finck return TRUE;
3999c2c66affSColin Finck }
4000c2c66affSColin Finck
4001c2c66affSColin Finck if (cache_container_open_index(pContainer, MIN_BLOCK_NO))
4002c2c66affSColin Finck {
4003c2c66affSColin Finck memset(pftLastModified, 0, sizeof(*pftLastModified));
4004c2c66affSColin Finck return TRUE;
4005c2c66affSColin Finck }
4006c2c66affSColin Finck
4007c2c66affSColin Finck if (!(pHeader = cache_container_lock_index(pContainer)))
4008c2c66affSColin Finck {
4009c2c66affSColin Finck memset(pftLastModified, 0, sizeof(*pftLastModified));
4010c2c66affSColin Finck return TRUE;
4011c2c66affSColin Finck }
4012c2c66affSColin Finck
4013c2c66affSColin Finck if (!urlcache_find_hash_entry(pHeader, url, &pHashEntry))
4014c2c66affSColin Finck {
4015c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
4016c2c66affSColin Finck memset(pftLastModified, 0, sizeof(*pftLastModified));
4017c2c66affSColin Finck TRACE("entry %s not found!\n", url);
4018c2c66affSColin Finck return TRUE;
4019c2c66affSColin Finck }
4020c2c66affSColin Finck
4021c2c66affSColin Finck pEntry = (const entry_header*)((LPBYTE)pHeader + pHashEntry->offset);
4022c2c66affSColin Finck if (pEntry->signature != URL_SIGNATURE)
4023c2c66affSColin Finck {
4024ef9a828eSwinesync FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPCSTR)&pEntry->signature, sizeof(DWORD)));
4025c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
4026c2c66affSColin Finck memset(pftLastModified, 0, sizeof(*pftLastModified));
4027c2c66affSColin Finck return TRUE;
4028c2c66affSColin Finck }
4029c2c66affSColin Finck
4030c2c66affSColin Finck pUrlEntry = (const entry_url *)pEntry;
4031c2c66affSColin Finck expired = urlcache_entry_is_expired(pUrlEntry, pftLastModified);
4032c2c66affSColin Finck
4033c2c66affSColin Finck cache_container_unlock_index(pContainer, pHeader);
4034c2c66affSColin Finck
4035c2c66affSColin Finck return expired;
4036c2c66affSColin Finck }
4037c2c66affSColin Finck
4038c2c66affSColin Finck /***********************************************************************
4039c2c66affSColin Finck * IsUrlCacheEntryExpiredW (WININET.@)
4040c2c66affSColin Finck *
4041c2c66affSColin Finck * PARAMS
4042c2c66affSColin Finck * url [I] Url
4043c2c66affSColin Finck * dwFlags [I] Unknown
4044c2c66affSColin Finck * pftLastModified [O] Last modified time
4045c2c66affSColin Finck */
IsUrlCacheEntryExpiredW(LPCWSTR url,DWORD dwFlags,FILETIME * pftLastModified)4046c2c66affSColin Finck BOOL WINAPI IsUrlCacheEntryExpiredW(LPCWSTR url, DWORD dwFlags, FILETIME* pftLastModified)
4047c2c66affSColin Finck {
4048c2c66affSColin Finck char *encoded_url;
4049c2c66affSColin Finck BOOL ret;
4050c2c66affSColin Finck
4051c2c66affSColin Finck if(!urlcache_encode_url_alloc(url, &encoded_url))
4052c2c66affSColin Finck return FALSE;
4053c2c66affSColin Finck
4054c2c66affSColin Finck ret = IsUrlCacheEntryExpiredA(encoded_url, dwFlags, pftLastModified);
4055c2c66affSColin Finck heap_free(encoded_url);
4056c2c66affSColin Finck return ret;
4057c2c66affSColin Finck }
4058c2c66affSColin Finck
4059c2c66affSColin Finck /***********************************************************************
4060c2c66affSColin Finck * GetDiskInfoA (WININET.@)
4061c2c66affSColin Finck */
GetDiskInfoA(PCSTR path,PDWORD cluster_size,PDWORDLONG free,PDWORDLONG total)4062c2c66affSColin Finck BOOL WINAPI GetDiskInfoA(PCSTR path, PDWORD cluster_size, PDWORDLONG free, PDWORDLONG total)
4063c2c66affSColin Finck {
4064c2c66affSColin Finck BOOL ret;
4065c2c66affSColin Finck ULARGE_INTEGER bytes_free, bytes_total;
4066c2c66affSColin Finck
4067c2c66affSColin Finck TRACE("(%s, %p, %p, %p)\n", debugstr_a(path), cluster_size, free, total);
4068c2c66affSColin Finck
4069c2c66affSColin Finck if (!path)
4070c2c66affSColin Finck {
4071c2c66affSColin Finck SetLastError(ERROR_INVALID_PARAMETER);
4072c2c66affSColin Finck return FALSE;
4073c2c66affSColin Finck }
4074c2c66affSColin Finck
4075c2c66affSColin Finck if ((ret = GetDiskFreeSpaceExA(path, NULL, &bytes_total, &bytes_free)))
4076c2c66affSColin Finck {
4077c2c66affSColin Finck if (cluster_size) *cluster_size = 1;
4078c2c66affSColin Finck if (free) *free = bytes_free.QuadPart;
4079c2c66affSColin Finck if (total) *total = bytes_total.QuadPart;
4080c2c66affSColin Finck }
4081c2c66affSColin Finck return ret;
4082c2c66affSColin Finck }
4083c2c66affSColin Finck
4084c2c66affSColin Finck /***********************************************************************
4085c2c66affSColin Finck * RegisterUrlCacheNotification (WININET.@)
4086c2c66affSColin Finck */
RegisterUrlCacheNotification(LPVOID a,DWORD b,DWORD c,DWORD d,DWORD e,DWORD f)4087c2c66affSColin Finck DWORD WINAPI RegisterUrlCacheNotification(LPVOID a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f)
4088c2c66affSColin Finck {
4089c2c66affSColin Finck FIXME("(%p %x %x %x %x %x)\n", a, b, c, d, e, f);
4090c2c66affSColin Finck return 0;
4091c2c66affSColin Finck }
4092c2c66affSColin Finck
4093c2c66affSColin Finck /***********************************************************************
4094c2c66affSColin Finck * IncrementUrlCacheHeaderData (WININET.@)
4095c2c66affSColin Finck */
IncrementUrlCacheHeaderData(DWORD index,LPDWORD data)4096c2c66affSColin Finck BOOL WINAPI IncrementUrlCacheHeaderData(DWORD index, LPDWORD data)
4097c2c66affSColin Finck {
4098c2c66affSColin Finck FIXME("(%u, %p)\n", index, data);
4099c2c66affSColin Finck return FALSE;
4100c2c66affSColin Finck }
4101c2c66affSColin Finck
4102c2c66affSColin Finck /***********************************************************************
4103c2c66affSColin Finck * RunOnceUrlCache (WININET.@)
4104c2c66affSColin Finck */
4105c2c66affSColin Finck
RunOnceUrlCache(HWND hwnd,HINSTANCE hinst,LPSTR cmd,int cmdshow)4106c2c66affSColin Finck DWORD WINAPI RunOnceUrlCache(HWND hwnd, HINSTANCE hinst, LPSTR cmd, int cmdshow)
4107c2c66affSColin Finck {
4108c2c66affSColin Finck FIXME("(%p, %p, %s, %d): stub\n", hwnd, hinst, debugstr_a(cmd), cmdshow);
4109c2c66affSColin Finck return 0;
4110c2c66affSColin Finck }
4111c2c66affSColin Finck
init_urlcache(void)4112c2c66affSColin Finck BOOL init_urlcache(void)
4113c2c66affSColin Finck {
4114c2c66affSColin Finck dll_unload_event = CreateEventW(NULL, FALSE, FALSE, NULL);
4115c2c66affSColin Finck if(!dll_unload_event)
4116c2c66affSColin Finck return FALSE;
4117c2c66affSColin Finck
4118c2c66affSColin Finck free_cache_running = CreateSemaphoreW(NULL, 1, 1, NULL);
4119c2c66affSColin Finck if(!free_cache_running) {
4120c2c66affSColin Finck CloseHandle(dll_unload_event);
4121c2c66affSColin Finck return FALSE;
4122c2c66affSColin Finck }
4123c2c66affSColin Finck
4124c2c66affSColin Finck #ifndef __REACTOS__
4125c2c66affSColin Finck cache_containers_init();
4126c2c66affSColin Finck #endif
4127c2c66affSColin Finck return TRUE;
4128c2c66affSColin Finck }
4129c2c66affSColin Finck
free_urlcache(void)4130c2c66affSColin Finck void free_urlcache(void)
4131c2c66affSColin Finck {
4132c2c66affSColin Finck SetEvent(dll_unload_event);
4133c2c66affSColin Finck WaitForSingleObject(free_cache_running, INFINITE);
4134c2c66affSColin Finck ReleaseSemaphore(free_cache_running, 1, NULL);
4135c2c66affSColin Finck CloseHandle(free_cache_running);
4136c2c66affSColin Finck CloseHandle(dll_unload_event);
4137c2c66affSColin Finck
4138c2c66affSColin Finck cache_containers_free();
4139c2c66affSColin Finck }
4140c2c66affSColin Finck
4141c2c66affSColin Finck /***********************************************************************
4142c2c66affSColin Finck * LoadUrlCacheContent (WININET.@)
4143c2c66affSColin Finck */
LoadUrlCacheContent(void)4144c2c66affSColin Finck BOOL WINAPI LoadUrlCacheContent(void)
4145c2c66affSColin Finck {
4146c2c66affSColin Finck FIXME("stub!\n");
4147c2c66affSColin Finck return FALSE;
4148c2c66affSColin Finck }
4149