Los rincones del API Win32: El caché de WinInet - Enumerar las entradas almacenadas en el caché
27 de Agosto de 2005
Programación estructurada
De una forma similar a lo que nos ocurría con el protocolo FTP, tenemos que hacer uso de tres funciones, una para iniciar la búsqueda y recuperar la primera entrada, otra para recuperar las siguientes entradas y otra para finalizarla.
Vamos a ver los detalles de cada una de estas funciones:
HANDLE FindFirstUrlCacheEntry( LPCTSTR lpszPatrónBúsqueda, LPINTERNET_CACHE_ENTRY_INFOA lpInformaciónEntrada, LPDWORD lpdwLongitudInformaciónEntrada );
La función retorna un descriptor de búsqueda que nos servirá para obtener las siguientes entradas. Si se ha producido un error, se retornará NULL, y debemos comprobar el valor de GetLastError() para saber qué ha ocurrido. Una de las posibles causas de error es que el tamaño reservado para la estructura sea insuficiente. En este caso, la llamada a GetLastError() retornará ERROR_INSUFFICIENT_BUFFER, y en el parámetro "lpdwLongitudInformaciónEntrada" se habrá copiado el tamaño requerido.
En este punto hay que tener en cuenta todo lo que hablamos sobre la fragmentación y la memoria dinámica, en el artículo sobre “Los montones∞”. Si recordamos, dijimos que como norma general, siempre que hubiese que ampliar un buffer, había que duplicar su tamaño. Este es uno de los casos, ya que hay que ir ampliando el espacio reservado para la estructura, hasta que la función FindFirstUrlCacheEntry retorne un valor correcto.
En caso de error, GetLastError() puede retornar ERROR_NO_MORE_ITEMS, lo que significa que no hay ninguna entrada que cumpla los criterios de búsqueda.
En el siguiente código podemos ver cómo hacer una llamada típica, redimensionando el buffer hasta su tamaño correcto:
{ LPINTERNET_CACHE_ENTRY_INFO info; DWORD size, sizeReq; HANDLE busqueda = NULL; se establece un tamaño inicial arbitrario (potencia de dos) size = 128; ~= sizeof(INTERNET_CACHE_ENTRY_INFO) sizeReq = size; info = (LPINTERNET_CACHE_ENTRY_INFO) new char[size]; info->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFO); este bucle duplica el tamaño del buffer while (!busqueda) { busqueda = FindFirstUrlCacheEntry(NULL, info, &sizeReq); if (!busqueda) { delete [] info; se borra el buffer switch (GetLastError()) { era demasido pequeño: lo duplicamos case ERROR_INSUFFICIENT_BUFFER: size *= 2; sizeReq = size; info = (LPINTERNET_CACHE_ENTRY_INFO) new char[size]; info->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFO); break; no se ha encontrado ningún elemento case ERROR_NO_MORE_ITEMS: return ; otro error default: return -1; } } } aquí ya tenemos en "info" los datos de la primera entrada y podemos ir recuperando el resto de resultados. [...] }
Existe una función extendida llamada FindFirstUrlCacheEntryEx, con la que podemos localizar entradas de un tipo determinado, o pertenecientes a un grupo concreto. No voy a entrar en esta función ya que con la básica nos es suficiente por ahora.
El siguiente paso dentro de la enumeración de entradas es ir recuperando cada uno de los resultados.
Esto lo podemos conseguir a través de la función FindNextUrlCacheEntry, que tiene la siguiente sintaxis:
BOOL FindNextUrlCacheEntry( HANDLE hBusqueda, LPINTERNET_CACHE_ENTRY_INFO lpInformaciónEntrada, LPWORD lpdwLongitudInformaciónEntrada );
La función retorna TRUE o FALSE, dependiendo el éxito o fracaso. En esta función hay que tener las mismas precauciones que con FindFirstUrlCacheEntry, a la hora de reservar tamaño para la estructura de tamaño variable. Si la función retorna FALSE, y la llamada a GetLastError() retorna ERROR_INSUFFICIENT_BUFFER, debemos ampliar el tamaño reservado para la estructura INTERNET_CACHE_ENTRY_INFO.
Cuando la función retorne FALSE y la llamada a GetLastError() sea ERROR_NO_MORE_ITEMS, se puede dar por terminada la búsqueda, ya que no hay más resultados.
Y por último, debemos cerrar el descriptor de la búsqueda, utilizando la función FindCloseUrlCache:
BOOL FindCloseUrlCache( HANDLE hBusqueda );
Simplemente debemos pasar el descriptor de la búsqueda obtenido con FindFirstUrlCacheEntry ó FindFirstUrlCacheEntryEx, la función retornará TRUE si el descriptor se ha cerrado correctamente.
Vamos a ver los detalles de cada una de estas funciones:
HANDLE FindFirstUrlCacheEntry( LPCTSTR lpszPatrónBúsqueda, LPINTERNET_CACHE_ENTRY_INFOA lpInformaciónEntrada, LPDWORD lpdwLongitudInformaciónEntrada );
- lpszPatrónBúsqueda: se trata de una cadena que almacena el patrón de búsqueda. Se pueden utilizar los comodines típicos, como "*" y "?", y las cadenas especiales "visited:" o "cookie:", para recuperar las entradas del historial y las cookies respectivamente.
- lpInformaciónEntrada: es un puntero a una estructura de tipo INTERNET_CACHE_ENTRY_INFO que almacena los datos de la entrada del caché. La definición de esta estructura es bastante compleja, ya que su tamaño no es fijo, sino que depende de los datos que estén almacenados. Sin embargo, vamos a explicar los atributos más importantes:
- dwStructSize: el valor obtenido de sizeof(INTERNET_CACHE_ENTRY_INFO)
- lpszSourceUrlName: una cadena con la URL de la entrada.
- lpszLocalFileName: una cadena con la ruta del archivo local que almacena la entrada.
- CacheEntryType: se trata de una máscara de bits que indican el tipo de entrada. Actualmente todavía están por definir la mayoría de los tipos aunque hay algunos fijos:
- NORMAL_CACHE_ENTRY: entrada de caché normal.
- COOKIE_CACHE_ENTRY: entrada de caché de cookie.
- URLHISTORY_CACHE_ENTRY: entrada de caché de historial.
- dwUseCount: número de veces que la entrada del caché ha sido usada.
- dwHitRate: número de veces que la entrada del caché ha sido recuperada.
- dwSizeLow y dwSizeHigh: doble palabra baja y alta del tamaño del archivo.
- LastModifiedTime: la fecha y hora de la última modificación de la entrada.
- LastSyncTime: la fecha y hora en que la entrada fue sincronizada con el original por última vez.
- lpHeaderInfo: Un puntero a una zona de memoria que almacena las cabeceras de información. Esta zona de memoria en realidad está almacenada al final de la estructura, por eso es una estructura de tamaño variable.
- dwHeaderInfoSize: longitud del buffer apuntado por lpHeaderInfo.
- lpszFileExtension: un puntero a una cadena que almacena la extensión de la entrada. Esta zona de memoria, al igual que lpHeaderInfo, se sitúa al final de la estructura.
- lpdwLongitudInformaciónEntrada: el tamaño que hemos reservado para la estructura, pasado por referenia. Si se tratase de una estructura de tamaño fijo, nos valdría con indicar el valor sizeof(INTERNET_CACHE_ENTRY_INFO), sin embargo, al ser una estructura de tamaño variable, debemos pasar un valor, e ir ampliando la estructura hasta que sea suficiente. Al retornar la función, se copia en esta variable el tamaño necesitado.
La función retorna un descriptor de búsqueda que nos servirá para obtener las siguientes entradas. Si se ha producido un error, se retornará NULL, y debemos comprobar el valor de GetLastError() para saber qué ha ocurrido. Una de las posibles causas de error es que el tamaño reservado para la estructura sea insuficiente. En este caso, la llamada a GetLastError() retornará ERROR_INSUFFICIENT_BUFFER, y en el parámetro "lpdwLongitudInformaciónEntrada" se habrá copiado el tamaño requerido.
En este punto hay que tener en cuenta todo lo que hablamos sobre la fragmentación y la memoria dinámica, en el artículo sobre “Los montones∞”. Si recordamos, dijimos que como norma general, siempre que hubiese que ampliar un buffer, había que duplicar su tamaño. Este es uno de los casos, ya que hay que ir ampliando el espacio reservado para la estructura, hasta que la función FindFirstUrlCacheEntry retorne un valor correcto.
En caso de error, GetLastError() puede retornar ERROR_NO_MORE_ITEMS, lo que significa que no hay ninguna entrada que cumpla los criterios de búsqueda.
En el siguiente código podemos ver cómo hacer una llamada típica, redimensionando el buffer hasta su tamaño correcto:
{ LPINTERNET_CACHE_ENTRY_INFO info; DWORD size, sizeReq; HANDLE busqueda = NULL; se establece un tamaño inicial arbitrario (potencia de dos) size = 128; ~= sizeof(INTERNET_CACHE_ENTRY_INFO) sizeReq = size; info = (LPINTERNET_CACHE_ENTRY_INFO) new char[size]; info->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFO); este bucle duplica el tamaño del buffer while (!busqueda) { busqueda = FindFirstUrlCacheEntry(NULL, info, &sizeReq); if (!busqueda) { delete [] info; se borra el buffer switch (GetLastError()) { era demasido pequeño: lo duplicamos case ERROR_INSUFFICIENT_BUFFER: size *= 2; sizeReq = size; info = (LPINTERNET_CACHE_ENTRY_INFO) new char[size]; info->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFO); break; no se ha encontrado ningún elemento case ERROR_NO_MORE_ITEMS: return ; otro error default: return -1; } } } aquí ya tenemos en "info" los datos de la primera entrada y podemos ir recuperando el resto de resultados. [...] }
Existe una función extendida llamada FindFirstUrlCacheEntryEx, con la que podemos localizar entradas de un tipo determinado, o pertenecientes a un grupo concreto. No voy a entrar en esta función ya que con la básica nos es suficiente por ahora.
El siguiente paso dentro de la enumeración de entradas es ir recuperando cada uno de los resultados.
Esto lo podemos conseguir a través de la función FindNextUrlCacheEntry, que tiene la siguiente sintaxis:
BOOL FindNextUrlCacheEntry( HANDLE hBusqueda, LPINTERNET_CACHE_ENTRY_INFO lpInformaciónEntrada, LPWORD lpdwLongitudInformaciónEntrada );
- hBusqueda: un descriptor obtenido a través de una llamada a FindNextUrlCacheEntry.
- lpInformaciónEntrada: un puntero a una estructura de tamaño variable de tipo INTERNET_CACHE_ENTRY_INFO.
- lpdwLongitudInformaciónEntrada: un puntero a un valor de 32 bits que contiene el tamaño reservado para la estructura pasada en "lpInformaciónEntrada". Al retornar, la función copia en este parámetro el número de bytes copiados a la estructura.
La función retorna TRUE o FALSE, dependiendo el éxito o fracaso. En esta función hay que tener las mismas precauciones que con FindFirstUrlCacheEntry, a la hora de reservar tamaño para la estructura de tamaño variable. Si la función retorna FALSE, y la llamada a GetLastError() retorna ERROR_INSUFFICIENT_BUFFER, debemos ampliar el tamaño reservado para la estructura INTERNET_CACHE_ENTRY_INFO.
Cuando la función retorne FALSE y la llamada a GetLastError() sea ERROR_NO_MORE_ITEMS, se puede dar por terminada la búsqueda, ya que no hay más resultados.
Y por último, debemos cerrar el descriptor de la búsqueda, utilizando la función FindCloseUrlCache:
BOOL FindCloseUrlCache( HANDLE hBusqueda );
Simplemente debemos pasar el descriptor de la búsqueda obtenido con FindFirstUrlCacheEntry ó FindFirstUrlCacheEntryEx, la función retornará TRUE si el descriptor se ha cerrado correctamente.
Valora este capítulo:
Autor y licencia de 'Los rincones del API Win32: El caché de WinInet - Enumerar las entradas almacenadas en el caché'
|
Opiniona sobre 'Los rincones del API Win32: El caché de WinInet - Enumerar las entradas almacenadas en el caché' (0)
Tu nombre debe tener tres caracteres como mínimo.
Es necesario que te des de alta con una cuenta de correo válida.
Es necesario que te des de alta con una cuenta de correo válida.
El contenido del título de tu opinión debe tener tres caracteres como mínimo.
Es obligatorio que selecciones una valoración del recurso.
El contenido del comentario de tu opinión debe tener tres caracteres como mínimo.
Opina sobre este tutorial |
Wikis relacionados con 'Los rincones del API Win32: El caché de WinInet - Enumerar las entradas almacenadas en el caché'
Comienzo con un nuevo tema dentro dentro de la serie Los rincones del API Win32....
Más »
Entramos en temas interesantes: el acceso a recursos remotos a través del protocolo de aplicación...
Más »
En el anterior curso dejamos muchos temas en el tintero, así que voy a terminar...
Más »
Damos una visión detallada de una de las características más interesantes de esta tecnología de...
Más »
Curso que profundiza en el gestor de montones (o montículos) dentro de Win32, así como...
Más »


