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