Almacenamiento en caché (Windows Internet)

Las funciones winINet tienen compatibilidad sencilla, pero flexible y integrada con el almacenamiento en caché. Los datos recuperados de la red se almacenan en caché en el disco duro y se recuperan para las solicitudes posteriores. La aplicación puede controlar el almacenamiento en caché en cada solicitud. En el caso de las solicitudes HTTP del servidor, la mayoría de los encabezados recibidos también se almacenan en caché. Cuando se satisface una solicitud HTTP desde la memoria caché, los encabezados almacenados en caché también se devuelven al autor de la llamada. Esto hace que la descarga de datos sea perfecta, tanto si los datos proceden de la memoria caché como de la red.

Las aplicaciones deben asignar correctamente un búfer para obtener los resultados deseados al usar las funciones de almacenamiento en caché de direcciones URL persistentes. Para obtener más información, consulte Uso de búferes.

Comportamiento de caché durante el procesamiento de respuestas

La caché de WinINet es compatible con las directivas de control de caché HTTP descritas en RFC 2616. Las directivas de control de caché y las marcas de conjunto de aplicaciones determinan lo que se puede almacenar en caché; Sin embargo, WinINet determina qué se almacena realmente en caché en función del criterio siguiente:

  • WinINet solo almacena en caché las respuestas HTTP y FTP.
  • Solo las respuestas con buen comportamiento pueden almacenarse en una memoria caché y usarse en una respuesta a una solicitud posterior. Las respuestas bien comportadas se definen como respuestas que se devuelven correctamente.
  • De forma predeterminada, WinINet almacenará en caché las respuestas correctas a menos que una directiva de control de caché del servidor o una marca definida por la aplicación indique específicamente que es posible que la respuesta no se almacene en caché.
  • En general, las respuestas al verbo GET se almacenan en caché si se cumplen los requisitos enumerados anteriormente. Las respuestas a los verbos PUT y POST no se almacenan en caché en ninguna circunstancia.
  • Los elementos se almacenarán en caché incluso cuando la memoria caché esté llena. Si un elemento agregado coloca la memoria caché sobre el límite de tamaño, se programa el scavenger de caché. De forma predeterminada, no se garantiza que los elementos permanezcan más de 10 minutos en la memoria caché. Para obtener más información, consulte la sección Cache Scavenger a continuación.
  • Https se almacena en caché de forma predeterminada. Esto se administra mediante una configuración global que no se puede invalidar mediante directivas de caché definidas por la aplicación. Para invalidar la configuración global, seleccione el applet Opciones de Internet en el panel de control y vaya a la pestaña avanzada. Active la casilla "No guardar páginas cifradas en disco" en la sección "Seguridad".

Cache Scavenger

El scavenger de caché limpia periódicamente los elementos de la memoria caché. Si se agrega un elemento a la memoria caché y la memoria caché está llena, el elemento se agrega a la memoria caché y se programa el scavenger de caché. Si el scavenger de caché completa una ronda de scavenging y la caché no ha alcanzado el límite de caché, el scavenger se programa para otra ronda cuando se agrega otro elemento a la memoria caché. En general, el scavenger se programa cuando un elemento agregado coloca la memoria caché sobre su límite de tamaño. De forma predeterminada, el período mínimo de vida en la memoria caché se establece en 10 minutos a menos que se especifique lo contrario en una directiva de control de caché. Cuando se inicia el scavenger de caché, no hay ninguna garantía de que los elementos más antiguos sean los primeros en eliminarse de la memoria caché.

La memoria caché se comparte en todas las aplicaciones winINet del equipo para el mismo usuario. A partir de Windows Vista y Windows Server 2008, el tamaño de caché se establece en 1/32nd el tamaño del disco, con un tamaño mínimo de 8 MB y un tamaño máximo de 50 MB.

Uso de marcas para controlar el almacenamiento en caché

Las marcas de almacenamiento en caché permiten a una aplicación controlar cuándo y cómo usa la memoria caché. Estas marcas se pueden usar solas o en combinación con el parámetro dwFlags en funciones que acceden a la información o a los recursos de Internet. De forma predeterminada, las funciones almacenan todos los datos descargados de Internet.

Las marcas siguientes se pueden usar para controlar el almacenamiento en caché.

Value Significado
INTERNET_FLAG_CACHE_ASYNC Esta marca no tiene efecto.
INTERNET_FLAG_CACHE_IF_NET_FAIL Devuelve el recurso de la memoria caché si se produce un error en la solicitud de red del recurso debido a un error de ERROR_INTERNET_CONNECTION_RESET o ERROR_INTERNET_CANNOT_CONNECT . HttpOpenRequest usa esta marca.
INTERNET_FLAG_DONT_CACHE No almacena en caché los datos, ya sea localmente o en ninguna puerta de enlace. Idéntico al valor preferido, INTERNET_FLAG_NO_CACHE_WRITE.
Indica que se trata de un envío de formularios.
INTERNET_FLAG_FROM_CACHEINTERNET_FLAG_FORMS_SUBMIT No realiza solicitudes de red. Todas las entidades se devuelven de la memoria caché. Si el elemento solicitado no está en la memoria caché, se devuelve un error adecuado, como ERROR_FILE_NOT_FOUND. Solo la función InternetOpen usa esta marca.
INTERNET_FLAG_FWD_BACK Indica que la función debe usar la copia del recurso que se encuentra actualmente en la memoria caché de Internet. No se comprueba la fecha de expiración y otra información sobre el recurso. Si el elemento solicitado no se encuentra en la memoria caché de Internet, el sistema intenta localizar el recurso en la red. Este valor se introdujo en Microsoft Internet Explorer 5 y está asociado a las operaciones de botón Reenviar y Atrás de Internet Explorer.
INTERNET_FLAG_HYPERLINK Obliga a la aplicación a volver a cargar un recurso si no hay tiempo de expiración y no se devolvió ninguna hora de última modificación cuando el recurso se almacenó en la memoria caché.
INTERNET_FLAG_MAKE_PERSISTENT Ya no se admite.
INTERNET_FLAG_MUST_CACHE_REQUEST Hace que se cree un archivo temporal si el archivo no se puede almacenar en caché. Esto es idéntico al valor preferido, INTERNET_FLAG_NEED_FILE.
INTERNET_FLAG_NEED_FILE Hace que se cree un archivo temporal si el archivo no se puede almacenar en caché.
INTERNET_FLAG_NO_CACHE_WRITE Rechaza cualquier intento por parte de la función de almacenar los datos descargados de Internet en la memoria caché. Esta marca es necesaria si la aplicación no quiere que los recursos descargados se almacenen localmente.
INTERNET_FLAG_NO_UI Deshabilita el cuadro de diálogo cookie. Esta marca se puede usar en HttpOpenRequest e InternetOpenUrl (solo solicitudes HTTP).
INTERNET_FLAG_OFFLINE Impide que la aplicación envíe solicitudes a la red. Todas las solicitudes se resuelven mediante los recursos almacenados en la memoria caché. Si el recurso no está en la memoria caché, se devuelve un error adecuado, como ERROR_FILE_NOT_FOUND.
INTERNET_FLAG_PRAGMA_NOCACHE Fuerza a que el servidor de origen resuelva la solicitud, incluso si existe una copia almacenada en caché en el proxy. La función InternetOpenUrl (solo en solicitudes HTTP y HTTPS) y la función HttpOpenRequest usan esta marca.
INTERNET_FLAG_RELOAD Obliga a la función a recuperar el recurso solicitado directamente desde Internet. La información que se descarga se almacena en la memoria caché.
INTERNET_FLAG_RESYNCHRONIZE Hace que una aplicación realice una descarga condicional del recurso desde Internet. Si la versión almacenada en la memoria caché es actual, la información se descarga de la memoria caché. De lo contrario, la información se vuelve a cargar desde el servidor.

 

Funciones de almacenamiento en caché persistentes

Los clientes que necesitan servicios de almacenamiento en caché persistentes usan las funciones de almacenamiento en caché persistentes para permitir que sus aplicaciones guarden datos en el sistema de archivos local para su uso posterior, como en situaciones en las que un vínculo de ancho de banda bajo limita el acceso a los datos o el acceso no está disponible en absoluto.

Las funciones de caché proporcionan almacenamiento en caché persistente y exploración sin conexión. A menos que la marca INTERNET_FLAG_NO_CACHE_WRITE especifique explícitamente ningún almacenamiento en caché, las funciones almacenan en caché todos los datos descargados de la red. Las respuestas a los datos POST no se almacenan en caché.

Uso de las funciones de caché de direcciones URL persistentes

Las siguientes funciones de caché de direcciones URL persistentes permiten a una aplicación acceder a la información almacenada en la memoria caché y manipularla.

Función Descripción
CommitUrlCacheEntryA Almacena en caché los datos del archivo especificado en el almacenamiento de caché y los asocia a la dirección URL especificada.
CommitUrlCacheEntryW Almacena en caché los datos del archivo especificado en el almacenamiento de caché y los asocia a la dirección URL especificada.
CreateUrlCacheEntry Asigna el almacenamiento en caché solicitado y crea un nombre de archivo local para guardar la entrada de caché que corresponde al nombre de origen.
CreateUrlCacheGroup Genera una identificación de grupo de caché.
DeleteUrlCacheEntry Quita el archivo asociado al nombre de origen de la memoria caché, si el archivo existe.
DeleteUrlCacheGroup Libera un GROUPID y cualquier estado asociado en el archivo de índice de caché.
FindCloseUrlCache Cierra el identificador de enumeración especificado.
FindFirstUrlCacheEntry Comienza la enumeración de la memoria caché.
FindFirstUrlCacheEntryEx Comienza una enumeración filtrada de la memoria caché.
FindNextUrlCacheEntry Recupera la siguiente entrada de la memoria caché.
FindNextUrlCacheEntryEx Recupera la siguiente entrada en una enumeración de caché filtrada.
GetUrlCacheEntryInfo Recupera información sobre una entrada de caché.
GetUrlCacheEntryInfoEx Busca la dirección URL después de traducir las redirecciones almacenadas en caché que HttpSendRequest aplicaría en modo sin conexión.
ReadUrlCacheEntryStream Lee los datos almacenados en caché de una secuencia que se ha abierto mediante RetrieveUrlCacheEntryStream.
RetrieveUrlCacheEntryFile Recupera una entrada de caché de la memoria caché en forma de archivo.
RetrieveUrlCacheEntryStream Proporciona la manera más eficaz e independiente de la implementación de acceder a los datos de caché.
SetUrlCacheEntryGroup Agrega o quita entradas de un grupo de caché.
SetUrlCacheEntryInfo Establece los miembros especificados de la estructura INTERNET_CACHE_ENTRY_INFO .
UnlockUrlCacheEntryFile Desbloquea la entrada de caché que se bloqueó cuando el archivo se recuperó para su uso desde la memoria caché mediante RetrieveUrlCacheEntryFile.
UnlockUrlCacheEntryStream Cierra la secuencia que se ha recuperado mediante RetrieveUrlCacheEntryStream.

 

Enumeración de la memoria caché

Las funciones FindFirstUrlCacheEntry y FindNextUrlCacheEntry enumeran la información almacenada en la memoria caché. FindFirstUrlCacheEntry inicia la enumeración tomando un patrón de búsqueda, un búfer y un tamaño de búfer para crear un identificador y devolver la primera entrada de caché. FindNextUrlCacheEntry toma el identificador creado por FindFirstUrlCacheEntry, un búfer y un tamaño de búfer para devolver la siguiente entrada de caché.

Ambas funciones almacenan una estructura de INTERNET_CACHE_ENTRY_INFO en el búfer. El tamaño de esta estructura varía para cada entrada. Si el tamaño del búfer pasado a cualquiera de las funciones no es suficiente, se produce un error en la función y GetLastError devuelve ERROR_INSUFFICIENT_BUFFER. La variable de tamaño del búfer contiene el tamaño del búfer necesario para recuperar esa entrada de caché. Se debe asignar un búfer del tamaño indicado por la variable de tamaño del búfer y se debe llamar a la función de nuevo con el nuevo búfer.

La estructura INTERNET_CACHE_ENTRY_INFO contiene el tamaño de la estructura, la dirección URL de la información almacenada en caché, el nombre de archivo local, el tipo de entrada de caché, el recuento de uso, la tasa de aciertos, el tamaño, la hora de la última modificación, la expiración, el último acceso, la hora sincronizada, la información de encabezado, el tamaño de la información de encabezado y la extensión de nombre de archivo.

La función FindFirstUrlCacheEntry toma un patrón de búsqueda, un búfer que almacena la estructura INTERNET_CACHE_ENTRY_INFO y el tamaño del búfer. Actualmente, solo se implementa el patrón de búsqueda predeterminado, que devuelve todas las entradas de caché.

Una vez enumerada la memoria caché, la aplicación debe llamar a FindCloseUrlCache para cerrar el identificador de enumeración de caché.

En el ejemplo siguiente se muestra la dirección URL de cada entrada de caché en un cuadro de lista, IDC_CacheList. Usa MAX_CACHE_ENTRY_INFO_SIZE para asignar inicialmente un búfer, ya que las versiones anteriores de la API de WinINet no enumeran correctamente la memoria caché. Las versiones posteriores enumeran correctamente la memoria caché y no hay ningún límite de tamaño de caché. Todas las aplicaciones que se ejecutan en equipos con la versión de la API de WinINet de Internet Explorer 4.0 deben asignar un búfer del tamaño necesario. Para obtener más información, consulte Uso de búferes.

int WINAPI EnumerateCacheOld(HWND hX)
{
    DWORD dwEntrySize;
    LPINTERNET_CACHE_ENTRY_INFO lpCacheEntry;
    DWORD MAX_CACHE_ENTRY_INFO_SIZE = 4096;
    HANDLE hCacheDir;
    int nCount=0;

    SendDlgItemMessage(hX,IDC_CacheList,LB_RESETCONTENT,0,0);
    
    SetCursor(LoadCursor(NULL,IDC_WAIT));

    dwEntrySize = MAX_CACHE_ENTRY_INFO_SIZE;
    lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];
    lpCacheEntry->dwStructSize = dwEntrySize;

again:

    hCacheDir = FindFirstUrlCacheEntry(NULL,
                                       lpCacheEntry,
                                       &dwEntrySize);
    if (!hCacheDir)                                             
    {
        delete[]lpCacheEntry;
        switch(GetLastError())
        {
            case ERROR_NO_MORE_ITEMS: 
                TCHAR tempout[80];
                _stprintf_s(tempout, 
                            80,   
                            TEXT("The number of cache entries = %d \n"),
                            nCount);
                MessageBox(hX,tempout,TEXT("Cache Enumeration"),MB_OK);
                FindCloseUrlCache(hCacheDir);
                SetCursor(LoadCursor(NULL,IDC_ARROW));
                return TRUE;
                break;
            case ERROR_INSUFFICIENT_BUFFER:
                lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) 
                                new char[dwEntrySize];
                lpCacheEntry->dwStructSize = dwEntrySize;
                goto again;
                break;
            default:
                ErrorOut( hX,GetLastError(),
                          TEXT("FindNextUrlCacheEntry Init"));
                FindCloseUrlCache(hCacheDir);
                SetCursor(LoadCursor(NULL,IDC_ARROW));
                return FALSE;
        }
    }

    SendDlgItemMessage(hX,IDC_CacheList,LB_ADDSTRING,
                       0,(LPARAM)(lpCacheEntry->lpszSourceUrlName));
    nCount++;
    delete (lpCacheEntry);

    do 
    {
        dwEntrySize = MAX_CACHE_ENTRY_INFO_SIZE;
        lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize];
        lpCacheEntry->dwStructSize = dwEntrySize;

retry:
        if (!FindNextUrlCacheEntry(hCacheDir,
                                   lpCacheEntry, 
                                   &dwEntrySize))
        {
            delete[]lpCacheEntry;
            switch(GetLastError())
            {
                case ERROR_NO_MORE_ITEMS: 
                    TCHAR tempout[80];
                    _stprintf_s(tempout,
                                80,
                                TEXT("The number of cache entries = %d \n"),nCount);
                    MessageBox(hX,
                               tempout,
                               TEXT("Cache Enumeration"),MB_OK);
                    FindCloseUrlCache(hCacheDir);
                    return TRUE;
                    break;
                case ERROR_INSUFFICIENT_BUFFER:
                    lpCacheEntry = 
                             (LPINTERNET_CACHE_ENTRY_INFO) 
                              new char[dwEntrySize];
                    lpCacheEntry->dwStructSize = dwEntrySize;
                    goto retry;
                    break;
                default:
                    ErrorOut(hX,
                             GetLastError(),
                             TEXT("FindNextUrlCacheEntry Init"));
                    FindCloseUrlCache(hCacheDir);
                    return FALSE;
            }
        }

        SendDlgItemMessage(hX,
                           IDC_CacheList,LB_ADDSTRING,
                           0,
                          (LPARAM)(lpCacheEntry->lpszSourceUrlName));
        nCount++;
        delete[] lpCacheEntry;        
    }  while (TRUE);

    SetCursor(LoadCursor(NULL,IDC_ARROW));
    return TRUE;        
}

Recuperación de información de entrada de caché

La función GetUrlCacheEntryInfo permite recuperar la estructura de INTERNET_CACHE_ENTRY_INFO para la dirección URL especificada. Esta estructura contiene el tamaño de la estructura, la dirección URL de la información almacenada en caché, el nombre de archivo local, el tipo de entrada de caché, el recuento de uso, la tasa de aciertos, el tamaño, el tamaño de la última modificación, la hora de expiración, el último acceso, la hora de la última sincronización, la información de encabezado, el tamaño de la información de encabezado y la extensión de nombre de archivo.

GetUrlCacheEntryInfo acepta una dirección URL, un búfer para una estructura de INTERNET_CACHE_ENTRY_INFO y el tamaño del búfer. Si se encuentra la dirección URL, la información se copia en el búfer. De lo contrario, se produce un error en la función y GetLastError devuelve ERROR_FILE_NOT_FOUND. Si el tamaño del búfer no es suficiente para almacenar la información de entrada de caché, se produce un error en la función y GetLastError devuelve ERROR_INSUFFICIENT_BUFFER. El tamaño necesario para recuperar la información se almacena en la variable de tamaño del búfer.

GetUrlCacheEntryInfo no realiza ningún análisis de direcciones URL, por lo que no se encontrará una dirección URL que contenga un delimitador (#) en la memoria caché, incluso si el recurso está almacenado en caché. Por ejemplo, si la dirección URL "https://example.com/example.htm#sample" se pasa, la función devuelve ERROR_FILE_NOT_FOUND incluso si "https://example.com/example.htm" está en la memoria caché.

En el ejemplo siguiente se recupera la información de entrada de caché de la dirección URL especificada. A continuación, la función muestra la información de encabezado en el cuadro de edición IDC_CacheDump .

int WINAPI GetCacheEntryInfo(HWND hX,LPTSTR lpszUrl)
{
    DWORD dwEntrySize=0;
    LPINTERNET_CACHE_ENTRY_INFO lpCacheEntry;

    SetCursor(LoadCursor(NULL,IDC_WAIT));
    if (!GetUrlCacheEntryInfo(lpszUrl,NULL,&dwEntrySize))
    {
        if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER)
        {
            ErrorOut(hX,GetLastError(),TEXT("GetUrlCacheEntryInfo"));
            SetCursor(LoadCursor(NULL,IDC_ARROW));
            return FALSE;
        }
        else
            lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) 
                            new char[dwEntrySize];
    }
    else
        return FALSE; // should not be successful w/ NULL buffer
                      // and 0 size

    if (!GetUrlCacheEntryInfo(lpszUrl,lpCacheEntry,&dwEntrySize))
    {
        ErrorOut(hX,GetLastError(),TEXT("GetUrlCacheEntryInfo"));
        SetCursor(LoadCursor(NULL,IDC_ARROW));
        return FALSE;
    }
    else
    {
        if ((lpCacheEntry->dwHeaderInfoSize)!=0)
        {
            LPSTR(lpCacheEntry->lpHeaderInfo)
                                [lpCacheEntry->dwHeaderInfoSize]=TEXT('\0');
            SetDlgItemText(hX,IDC_Headers,
                           lpCacheEntry->lpHeaderInfo);
        }
        else
        {
            SetDlgItemText(hX,IDC_Headers,TEXT("None"));
        }

        SetCursor(LoadCursor(NULL,IDC_ARROW));
        return TRUE;
    }
        
}

Crear una entrada de caché

Una aplicación usa las funciones CreateUrlCacheEntry y CommitUrlCacheEntry para crear una entrada de caché.

CreateUrlCacheEntry acepta la dirección URL, el tamaño de archivo esperado y la extensión de nombre de archivo. A continuación, la función crea un nombre de archivo local para guardar la entrada de caché que corresponde a la dirección URL y la extensión de nombre de archivo.

Con el nombre de archivo local, escriba los datos en el archivo local. Una vez escritos los datos en el archivo local, la aplicación debe llamar a CommitUrlCacheEntry.

CommitUrlCacheEntry acepta la dirección URL, el nombre de archivo local, la expiración, la hora de última modificación, el tipo de entrada de caché, la información de encabezado, el tamaño de la información del encabezado y la extensión de nombre de archivo. A continuación, la función almacena en caché los datos del archivo especificado en el almacenamiento de caché y lo asocia a la dirección URL especificada.

En el ejemplo siguiente se usa el nombre de archivo local, creado por una llamada anterior a CreateUrlCacheEntry, almacenado en el cuadro de texto, IDC_LocalFile, para almacenar el texto del cuadro de texto, IDC_CacheDump, en la entrada de caché. Una vez escritos los datos en el archivo mediante fopen, fprintf y fclose, la entrada se confirma mediante CommitUrlCacheEntry.

int WINAPI CommitEntry(HWND hX)
{
    LPTSTR lpszUrl, lpszExt, lpszFileName;
    LPTSTR lpszData,lpszSize;
    DWORD dwSize;
    DWORD dwEntryType=0;
    FILE *lpfCacheEntry;
    LPFILETIME lpdtmExpire, lpdtmLastModified;
    LPSYSTEMTIME lpdtmSysTime;
    errno_t err;

    if( SendDlgItemMessage(hX,IDC_RBNormal,BM_GETCHECK,0,0) )
    {
        dwEntryType = dwEntryType + NORMAL_CACHE_ENTRY;
    }
    else if( SendDlgItemMessage(hX,IDC_RBSticky, BM_GETCHECK,0,0) )
    {
        dwEntryType = dwEntryType + STICKY_CACHE_ENTRY;
    }
    else if(SendDlgItemMessage( hX,IDC_RBSparse, BM_GETCHECK,0,0) )
    {
        dwEntryType = dwEntryType + SPARSE_CACHE_ENTRY;
    }
 

    if( SendDlgItemMessage(hX,IDC_RBCookie, BM_GETCHECK,0,0))
    {
            dwEntryType = dwEntryType + COOKIE_CACHE_ENTRY;
    }
    else if( SendDlgItemMessage(hX,IDC_RBUrl, BM_GETCHECK,0,0) )
    {
        dwEntryType = dwEntryType + URLHISTORY_CACHE_ENTRY;
    }


    if( SendDlgItemMessage(hX,IDC_RBNone, BM_GETCHECK,0,0) )
    {
        dwEntryType=0;
    }
        
    lpdtmSysTime = new SYSTEMTIME;
    lpdtmExpire = new FILETIME;
    lpdtmLastModified = new FILETIME;

    GetLocalTime(lpdtmSysTime);
    SystemTimeToFileTime(lpdtmSysTime,lpdtmExpire);
    SystemTimeToFileTime(lpdtmSysTime,lpdtmLastModified);
    delete(lpdtmSysTime);

    lpszUrl = new TCHAR[MAX_PATH];
    lpszFileName = new TCHAR[MAX_PATH];
    lpszExt = new TCHAR[5];
    lpszSize = new TCHAR[10];

    GetDlgItemText(hX,IDC_SourceURL,lpszUrl,MAX_PATH);
    GetDlgItemText(hX,IDC_LocalFile,lpszFileName,MAX_PATH);
    GetDlgItemText(hX,IDC_FileExt,lpszExt,5);

    GetDlgItemText(hX,IDC_SizeLow,lpszSize,10);
    dwSize = (DWORD)_ttol(lpszSize);
    delete(lpszSize);

    if (dwSize==0)
    {
        if((MessageBox(hX,
                       TEXT("Incorrect File Size.\nUsing 8000 characters, Okay?\n"),
                       TEXT("Commit Entry"),MB_YESNO))
                        ==IDYES)
        {
            dwSize = 8000;
        }
        else
        {
            return FALSE;
        }
    }

    lpszData = new TCHAR[dwSize];
    GetDlgItemText(hX,IDC_CacheDump,lpszData,dwSize);
        
     err = _tfopen_s(&lpfCacheEntry,lpszFileName,_T("w"));
     if (err)
        return FALSE;
    fprintf(lpfCacheEntry,"%s",lpszData);
    fclose(lpfCacheEntry);
    delete(lpszData);

    if ( !CommitUrlCacheEntry( lpszUrl, 
                               lpszFileName, 
                               *lpdtmExpire,
                               *lpdtmLastModified, 
                               dwEntryType,
                               NULL,
                               0,
                               lpszExt,
                               0) )
    {
        ErrorOut(hX,GetLastError(),TEXT("Commit Cache Entry"));
        delete(lpszUrl);
        delete(lpszFileName);
        delete(lpszExt);
        delete(lpdtmExpire);
        delete(lpdtmLastModified);
        return FALSE;
    }
    else
    {
        delete(lpszUrl);
        delete(lpszFileName);
        delete(lpszExt);
        delete(lpdtmExpire);
        delete(lpdtmLastModified);
        return TRUE;
    }
}

Eliminación de una entrada de caché

La función DeleteUrlCacheEntry toma una dirección URL y quita el archivo de caché asociado. Si el archivo de caché no existe, se produce un error en la función y GetLastError devuelve ERROR_FILE_NOT_FOUND. Si el archivo de caché está bloqueado o en uso actualmente, se produce un error en la función y GetLastError devuelve ERROR_ACCESS_DENIED. El archivo se elimina cuando se desbloquea.

Recuperación de archivos de entrada de caché

Para las aplicaciones que requieren el nombre de archivo de un recurso, use las funciones RetrieveUrlCacheEntryFile y UnlockUrlCacheEntryFile . Las aplicaciones que no requieren el nombre de archivo deben usar las funciones RetrieveUrlCacheEntryStream, ReadUrlCacheEntryStream y UnlockUrlCacheEntryStream para recuperar la información de la memoria caché.

RetrieveUrlCacheEntryStream no realiza ningún análisis de direcciones URL, por lo que no se encontrará una dirección URL que contenga un delimitador (#) en la memoria caché, incluso si el recurso está almacenado en caché. Por ejemplo, si la dirección URL "https://example.com/example.htm#sample" se pasa, la función devuelve ERROR_FILE_NOT_FOUND incluso si "https://example.com/example.htm" está en la memoria caché.

RetrieveUrlCacheEntryFile acepta una dirección URL, un búfer que almacena la estructura INTERNET_CACHE_ENTRY_INFO y el tamaño del búfer. La función se recupera y bloquea para el autor de la llamada.

Una vez usada la información del archivo, la aplicación debe llamar a UnlockUrlCacheEntryFile para desbloquear el archivo.

Grupos de caché

Para crear un grupo de caché, se debe llamar a la función CreateUrlCacheGroup para generar un GROUPID para el grupo de caché. Las entradas se pueden agregar al grupo de caché proporcionando la dirección URL de la entrada de caché y la marca INTERNET_CACHE_GROUP_ADD a la función SetUrlCacheEntryGroup . Para quitar una entrada de caché de un grupo, pase la dirección URL de la entrada de caché y la marca INTERNET_CACHE_GROUP_REMOVE a SetUrlCacheEntryGroup.

Las funciones FindFirstUrlCacheEntryEx y FindNextUrlCacheEntryEx se pueden usar para enumerar las entradas de un grupo de caché especificado. Una vez completada la enumeración, la función debe llamar a FindCloseUrlCache.

Control de estructuras con información de tamaño variable

La memoria caché puede contener información de tamaño variable para cada dirección URL almacenada. Esto se refleja en la estructura INTERNET_CACHE_ENTRY_INFO . Cuando las funciones de caché devuelven esta estructura, crean un búfer que siempre es el tamaño de INTERNET_CACHE_ENTRY_INFO más cualquier información de tamaño variable. Si un miembro de puntero no es NULL, apunta al área de memoria inmediatamente después de la estructura. Al copiar el búfer devuelto por una función en otro búfer, los miembros del puntero deben corregirse para que apunten al lugar adecuado en el nuevo búfer, como se muestra en el ejemplo siguiente.

lpDstCEInfo->lpszSourceUrlName = 
    (LPINTERNET_CACHE_ENTRY_INFO) ((LPBYTE) lpSrcCEInfo + 
       ((DWORD)(lpOldCEInfo->lpszSourceUrlName) - (DWORD)lpOldCEInfo));

Algunas funciones de caché producen un error con el mensaje de error ERROR_INSUFFICIENT_BUFFER si especifica un búfer demasiado pequeño para contener la información de entrada de caché recuperada por la función. En este caso, la función también devuelve el tamaño necesario del búfer. A continuación, puede asignar un búfer del tamaño adecuado y volver a llamar a la función.

Nota:

WinINet no admite implementaciones de servidor. Además, no se debe usar desde un servicio. En el caso de las implementaciones de servidor o los servicios, use Servicios HTTP de Microsoft Windows (WinHTTP).