Compartilhar via


Cache (Internet do Windows)

As funções WinINet têm suporte a cache interno simples, mas flexível. Todos os dados recuperados da rede são armazenados em cache no disco rígido e recuperados para solicitações subsequentes. O aplicativo pode controlar o cache em cada solicitação. Para solicitações http do servidor, a maioria dos cabeçalhos recebidos também são armazenados em cache. Quando uma solicitação http é atendida do cache, os cabeçalhos armazenados em cache também são retornados ao chamador. Isso torna o download de dados contínuo, independentemente de os dados serem provenientes do cache ou da rede.

Os aplicativos devem alocar corretamente um buffer para obter os resultados desejados ao usar as funções de cache de URL persistentes. Para obter mais informações, consulte Usando buffers.

Comportamento do cache durante o processamento de resposta

O cache WinINet está em conformidade com as diretivas de controle de cache HTTP descritas em RFC 2616. As diretivas de controle de cache e os sinalizadores de conjunto de aplicativos determinam o que pode ser armazenado em cache; no entanto, o WinINet determina o que é realmente armazenado em cache com base no seguinte critério:

  • O WinINet armazena em cache apenas respostas HTTP e FTP.
  • Somente respostas bem comportadas podem ser armazenadas por um cache e usadas em uma resposta a uma solicitação subsequente. As respostas bem comportadas são definidas como respostas que retornam com êxito.
  • Por padrão, o WinINet armazenará em cache respostas bem-sucedidas, a menos que uma diretiva de controle de cache do servidor ou um sinalizador definido pelo aplicativo denote especificamente que a resposta pode não ser armazenada em cache.
  • Em geral, as respostas ao verbo GET serão armazenadas em cache se os requisitos listados acima forem atendidos. As respostas aos verbos PUT e POST não são armazenadas em cache em nenhuma circunstância.
  • Os itens serão armazenados em cache mesmo quando o cache estiver cheio. Se um item adicionado colocar o cache acima do limite de tamanho, o cache será agendado. Por padrão, não há garantia de que os itens permaneçam mais de 10 minutos no cache. Para obter mais informações, consulte a seção Cache Scavenger abaixo.
  • O Https é armazenado em cache por padrão. Isso é gerenciado por uma configuração global que não pode ser substituída por diretivas de cache definidas pelo aplicativo. Para substituir a configuração global, selecione o miniaplicativo Opções da Internet no painel de controle e vá para a guia avançado. Marque a caixa "Não salvar páginas criptografadas em disco" na seção "Segurança".

Cache Scavenger

O gerenciador de cache limpa periodicamente os itens do cache. Se um item for adicionado ao cache e o cache estiver cheio, o item será adicionado ao cache e o cache será agendado. Se o cache scavenger concluir uma rodada de limpeza e o cache não tiver atingido o limite de cache, o cache será agendado para outra rodada quando outro item for adicionado ao cache. Em geral, o catadores é agendado quando um item adicionado coloca o cache acima do limite de tamanho. Por padrão, o tempo mínimo de vida no cache é definido como 10 minutos, a menos que especificado de outra forma em uma diretiva de controle de cache. Quando o cache scavenger é iniciado, não há garantia de que os itens mais antigos são os primeiros a serem excluídos do cache.

O cache é compartilhado entre todos os aplicativos WinINet no computador para o mesmo usuário. A partir do Windows Vista e do Windows Server 2008, o tamanho do cache é definido como 1/32 do tamanho do disco, com um tamanho mínimo de 8 MB e um tamanho máximo de 50 MB.

Usando sinalizadores para controlar o cache

Os sinalizadores de cache permitem que um aplicativo controle quando e como ele usa o cache. Esses sinalizadores podem ser usados sozinhos ou em combinação com o parâmetro dwFlags em funções que acessam informações ou recursos na Internet. Por padrão, as funções armazenam todos os dados baixados da Internet.

Os sinalizadores a seguir podem ser usados para controlar o cache.

Valor Significado
INTERNET_FLAG_CACHE_ASYNC Este sinalizador não tem efeito.
INTERNET_FLAG_CACHE_IF_NET_FAIL Retorna o recurso do cache se a solicitação de rede para o recurso falhar devido a um erro de ERROR_INTERNET_CONNECTION_RESET ou ERROR_INTERNET_CANNOT_CONNECT . Esse sinalizador é usado por HttpOpenRequest.
INTERNET_FLAG_DONT_CACHE Não armazena em cache os dados, localmente ou em nenhum gateway. Idêntico ao valor preferencial, INTERNET_FLAG_NO_CACHE_WRITE.
Indica que este é um envio de Formulários.
INTERNET_FLAG_FROM_CACHEINTERNET_FLAG_FORMS_SUBMIT Não faz solicitações de rede. Todas as entidades são retornadas do cache. Se o item solicitado não estiver no cache, um erro adequado, como ERROR_FILE_NOT_FOUND, será retornado. Somente a função InternetOpen usa esse sinalizador.
INTERNET_FLAG_FWD_BACK Indica que a função deve usar a cópia do recurso que está atualmente no cache da Internet. A data de validade e outras informações sobre o recurso não estão marcadas. Se o item solicitado não for encontrado no cache da Internet, o sistema tentará localizar o recurso na rede. Esse valor foi introduzido no Microsoft Internet Explorer 5 e está associado às operações de botão Avançar e Voltar do Explorer internet.
INTERNET_FLAG_HYPERLINK Força o aplicativo a recarregar um recurso se nenhuma hora de expiração e nenhuma hora da última modificação tiver sido retornada quando o recurso foi armazenado no cache.
INTERNET_FLAG_MAKE_PERSISTENT Não tem mais suporte.
INTERNET_FLAG_MUST_CACHE_REQUEST Faz com que um arquivo temporário seja criado se o arquivo não puder ser armazenado em cache. Isso é idêntico ao valor preferencial, INTERNET_FLAG_NEED_FILE.
INTERNET_FLAG_NEED_FILE Faz com que um arquivo temporário seja criado se o arquivo não puder ser armazenado em cache.
INTERNET_FLAG_NO_CACHE_WRITE Rejeita qualquer tentativa da função de armazenar dados baixados da Internet no cache. Esse sinalizador será necessário se o aplicativo não quiser que nenhum recurso baixado seja armazenado localmente.
INTERNET_FLAG_NO_UI Desabilita a caixa de diálogo de cookie. Esse sinalizador pode ser usado por HttpOpenRequest e InternetOpenUrl (somente solicitações HTTP).
INTERNET_FLAG_OFFLINE Impede que o aplicativo envie solicitações para a rede. Todas as solicitações são resolvidas usando os recursos armazenados no cache. Se o recurso não estiver no cache, um erro adequado, como ERROR_FILE_NOT_FOUND, será retornado.
INTERNET_FLAG_PRAGMA_NOCACHE Força a solicitação a ser resolvida pelo servidor de origem, mesmo que exista uma cópia armazenada em cache no proxy. A função InternetOpenUrl (somente em solicitações HTTP e HTTPS) e a função HttpOpenRequest usam esse sinalizador.
INTERNET_FLAG_RELOAD Força a função a recuperar o recurso solicitado diretamente da Internet. As informações baixadas são armazenadas no cache.
INTERNET_FLAG_RESYNCHRONIZE Faz com que um aplicativo execute um download condicional do recurso da Internet. Se a versão armazenada no cache for atual, as informações serão baixadas do cache. Caso contrário, as informações serão recarregadas do servidor.

 

Funções de cache persistentes

Os clientes que precisam de serviços de cache persistentes usam as funções de cache persistentes para permitir que seus aplicativos salvem dados no sistema de arquivos local para uso subsequente, como em situações em que um link de baixa largura de banda limita o acesso aos dados ou o acesso não está disponível.

As funções de cache fornecem cache persistente e navegação offline. A menos que o sinalizador INTERNET_FLAG_NO_CACHE_WRITE não especifique explicitamente nenhum cache, as funções armazenam em cache todos os dados baixados da rede. As respostas aos dados POST não são armazenadas em cache.

Usando as funções de cache de URL persistente

As funções de cache de URL persistentes a seguir permitem que um aplicativo acesse e manipule informações armazenadas no cache.

Função Descrição
CommitUrlCacheEntryA Armazena dados em cache no arquivo especificado no armazenamento de cache e os associa à URL fornecida.
CommitUrlCacheEntryW Armazena dados em cache no arquivo especificado no armazenamento de cache e os associa à URL fornecida.
CreateUrlCacheEntry Aloca o armazenamento de cache solicitado e cria um nome de arquivo local para salvar a entrada de cache que corresponde ao nome de origem.
CreateUrlCacheGroup Gera uma identificação de grupo de cache.
DeleteUrlCacheEntry Remove o arquivo associado ao nome de origem do cache, se o arquivo existir.
DeleteUrlCacheGroup Libera um GROUPID e qualquer estado associado no arquivo de índice de cache.
FindCloseUrlCache Fecha o identificador de enumeração especificado.
FindFirstUrlCacheEntry Inicia a enumeração do cache.
FindFirstUrlCacheEntryEx Inicia uma enumeração filtrada do cache.
FindNextUrlCacheEntry Recupera a próxima entrada no cache.
FindNextUrlCacheEntryEx Recupera a próxima entrada em uma enumeração de cache filtrada.
GetUrlCacheEntryInfo Recupera informações sobre uma entrada de cache.
GetUrlCacheEntryInfoEx Pesquisa a URL depois de traduzir os redirecionamentos armazenados em cache que seriam aplicados no modo offline por HttpSendRequest.
ReadUrlCacheEntryStream Lê os dados armazenados em cache de um fluxo que foi aberto usando RetrieveUrlCacheEntryStream.
RetrieveUrlCacheEntryFile Recupera uma entrada de cache do cache na forma de um arquivo.
RetrieveUrlCacheEntryStream Fornece a maneira mais eficiente e independente de implementação de acessar os dados de cache.
SetUrlCacheEntryGroup Adiciona ou remove entradas de um grupo de cache.
SetUrlCacheEntryInfo Define os membros especificados da estrutura INTERNET_CACHE_ENTRY_INFO .
UnlockUrlCacheEntryFile Desbloqueia a entrada de cache que foi bloqueada quando o arquivo foi recuperado para uso do cache por RetrieveUrlCacheEntryFile.
UnlockUrlCacheEntryStream Fecha o fluxo que foi recuperado usando RetrieveUrlCacheEntryStream.

 

Enumerando o cache

As funções FindFirstUrlCacheEntry e FindNextUrlCacheEntry enumeram as informações armazenadas no cache. FindFirstUrlCacheEntry inicia a enumeração usando um padrão de pesquisa, um buffer e um tamanho de buffer para criar um identificador e retornar a primeira entrada de cache. FindNextUrlCacheEntry usa o identificador criado por FindFirstUrlCacheEntry, um buffer e um tamanho de buffer para retornar a próxima entrada de cache.

Ambas as funções armazenam uma estrutura INTERNET_CACHE_ENTRY_INFO no buffer. O tamanho dessa estrutura varia para cada entrada. Se o tamanho do buffer passado para qualquer função for insuficiente, a função falhará e GetLastError retornará ERROR_INSUFFICIENT_BUFFER. A variável de tamanho do buffer contém o tamanho do buffer necessário para recuperar essa entrada de cache. Um buffer do tamanho indicado pela variável de tamanho do buffer deve ser alocado e a função deve ser chamada novamente com o novo buffer.

A estrutura INTERNET_CACHE_ENTRY_INFO contém o tamanho da estrutura, a URL das informações armazenadas em cache, o nome do arquivo local, o tipo de entrada do cache, a contagem de uso, a taxa de ocorrência, o tamanho, a hora da última modificação, a expiração, o último acesso, a hora sincronizada da última, as informações do cabeçalho, o tamanho das informações do cabeçalho e a extensão do nome do arquivo.

A função FindFirstUrlCacheEntry usa um padrão de pesquisa, um buffer que armazena a estrutura INTERNET_CACHE_ENTRY_INFO e o tamanho do buffer. Atualmente, somente o padrão de pesquisa padrão, que retorna todas as entradas de cache, é implementado.

Depois que o cache for enumerado, o aplicativo deverá chamar FindCloseUrlCache para fechar o identificador de enumeração de cache.

O exemplo a seguir exibe a URL de cada entrada de cache em uma caixa de listagem , IDC_CacheList. Ele usa MAX_CACHE_ENTRY_INFO_SIZE para alocar inicialmente um buffer, já que as versões iniciais da API WinINet não enumeram o cache corretamente de outra forma. Versões posteriores enumeram o cache corretamente e não há limite de tamanho de cache. Todos os aplicativos executados em computadores com a versão da API WinINet da Internet Explorer 4.0 devem alocar um buffer do tamanho necessário. Para obter mais informações, consulte Usando buffers.

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;        
}

Recuperando informações de entrada de cache

A função GetUrlCacheEntryInfo permite recuperar a estrutura INTERNET_CACHE_ENTRY_INFO para a URL especificada. Essa estrutura contém o tamanho da estrutura, a URL das informações armazenadas em cache, o nome do arquivo local, o tipo de entrada do cache, a contagem de uso, a taxa de ocorrência, o tamanho, a hora da última modificação, a expiração, o último acesso, a hora sincronizada da última, as informações do cabeçalho, o tamanho das informações do cabeçalho e a extensão do nome do arquivo.

GetUrlCacheEntryInfo aceita uma URL, um buffer para uma estrutura de INTERNET_CACHE_ENTRY_INFO e o tamanho do buffer. Se a URL for encontrada, as informações serão copiadas para o buffer. Caso contrário, a função falhará e GetLastError retornará ERROR_FILE_NOT_FOUND. Se o tamanho do buffer for insuficiente para armazenar as informações de entrada de cache, a função falhará e GetLastError retornará ERROR_INSUFFICIENT_BUFFER. O tamanho necessário para recuperar as informações é armazenado na variável de tamanho do buffer.

GetUrlCacheEntryInfo não faz nenhuma análise de URL, portanto, uma URL que contém uma âncora (#) não será encontrada no cache, mesmo que o recurso seja armazenado em cache. Por exemplo, se a URL "https://example.com/example.htm#sample" é passada, a função retorna ERROR_FILE_NOT_FOUND mesmo que "https://example.com/example.htm" está no cache.

O exemplo a seguir recupera as informações de entrada de cache para a URL especificada. Em seguida, a função exibe as informações de cabeçalho na caixa de edição 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;
    }
        
}

Criando uma entrada de cache

Um aplicativo usa as funções CreateUrlCacheEntry e CommitUrlCacheEntry para criar uma entrada de cache.

CreateUrlCacheEntry aceita a URL, o tamanho do arquivo esperado e a extensão de nome de arquivo. Em seguida, a função cria um nome de arquivo local para salvar a entrada de cache que corresponde à URL e à extensão de nome de arquivo.

Usando o nome do arquivo local, escreva os dados no arquivo local. Depois que os dados forem gravados no arquivo local, o aplicativo deverá chamar CommitUrlCacheEntry.

CommitUrlCacheEntry aceita a URL, o nome do arquivo local, a expiração, a hora da última modificação, o tipo de entrada de cache, as informações de cabeçalho, o tamanho das informações do cabeçalho e a extensão do nome do arquivo. Em seguida, a função armazena dados em cache no arquivo especificado no armazenamento de cache e os associa à URL fornecida.

O exemplo a seguir usa o nome do arquivo local, criado por uma chamada anterior para CreateUrlCacheEntry, armazenado na caixa de texto, IDC_LocalFile, para armazenar o texto da caixa de texto, IDC_CacheDump, na entrada de cache. Depois que os dados forem gravados no arquivo usando fopen, fprintf e fclose, a entrada será confirmada usando 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;
    }
}

Excluindo uma entrada de cache

A função DeleteUrlCacheEntry usa uma URL e remove o arquivo de cache associado a ela. Se o arquivo de cache não existir, a função falhará e GetLastError retornará ERROR_FILE_NOT_FOUND. Se o arquivo de cache estiver bloqueado ou em uso no momento, a função falhará e GetLastError retornará ERROR_ACCESS_DENIED. O arquivo é excluído quando desbloqueado.

Recuperando arquivos de entrada de cache

Para aplicativos que exigem o nome de arquivo de um recurso, use as funções RetrieveUrlCacheEntryFile e UnlockUrlCacheEntryFile . Os aplicativos que não exigem o nome do arquivo devem usar as funções RetrieveUrlCacheEntryStream, ReadUrlCacheEntryStream e UnlockUrlCacheEntryStream para recuperar as informações no cache.

RetrieveUrlCacheEntryStream não faz nenhuma análise de URL, portanto, uma URL que contém uma âncora (#) não será encontrada no cache, mesmo que o recurso seja armazenado em cache. Por exemplo, se a URL "https://example.com/example.htm#sample" é passada, a função retorna ERROR_FILE_NOT_FOUND mesmo que "https://example.com/example.htm" está no cache.

RetrieveUrlCacheEntryFile aceita uma URL, um buffer que armazena a estrutura INTERNET_CACHE_ENTRY_INFO e o tamanho do buffer. A função é recuperada e bloqueada para o chamador.

Depois que as informações no arquivo forem usadas, o aplicativo deverá chamar UnlockUrlCacheEntryFile para desbloquear o arquivo.

Grupos de Cache

Para criar um grupo de cache, a função CreateUrlCacheGroup deve ser chamada para gerar um GROUPID para o grupo de cache. As entradas podem ser adicionadas ao grupo de cache fornecendo a URL da entrada de cache e o sinalizador INTERNET_CACHE_GROUP_ADD para a função SetUrlCacheEntryGroup . Para remover uma entrada de cache de um grupo, passe a URL da entrada de cache e o sinalizador INTERNET_CACHE_GROUP_REMOVE para SetUrlCacheEntryGroup.

As funções FindFirstUrlCacheEntryEx e FindNextUrlCacheEntryEx podem ser usadas para enumerar as entradas em um grupo de cache especificado. Depois que a enumeração for concluída, a função deverá chamar FindCloseUrlCache.

Manipulando estruturas com informações de tamanho variável

O cache pode conter informações de tamanho variável para cada URL armazenada. Isso se reflete na estrutura INTERNET_CACHE_ENTRY_INFO . Quando as funções de cache retornam essa estrutura, elas criam um buffer que é sempre o tamanho de INTERNET_CACHE_ENTRY_INFO mais qualquer informação de tamanho variável. Se um membro de ponteiro não for NULL, ele apontará para a área de memória imediatamente após a estrutura. Ao copiar o buffer retornado por uma função em outro buffer, os membros do ponteiro devem ser corrigidos para apontar para o local apropriado no novo buffer, como mostra o exemplo a seguir.

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

Algumas funções de cache falharão com a mensagem de erro ERROR_INSUFFICIENT_BUFFER se você especificar um buffer muito pequeno para conter as informações de entrada de cache recuperadas pela função. Nesse caso, a função também retorna o tamanho necessário do buffer. Em seguida, você pode alocar um buffer do tamanho apropriado e chamar a função novamente.

Observação

O WinINet não dá suporte a implementações de servidor. Além disso, ele não deve ser usado de um serviço. Para implementações de servidor ou serviços, use Os Serviços HTTP do Microsoft Windows (WinHTTP).