Delen via


Algemene functies (Windows Internet)

De verschillende internetprotocollen (zoals ftp en http) gebruiken verschillende WinINet-functies om informatie op internet te verwerken. Deze algemene functies verwerken hun taken op een consistente manier, ongeacht het specifieke protocol waarop ze worden toegepast. Toepassingen kunnen deze functies gebruiken om functies voor algemeen gebruik te maken die taken verwerken in de verschillende protocollen (zoals het lezen van bestanden voor FTP en HTTP).

De algemene functies verwerken de volgende taken:

Algemene functies gebruiken

De volgende tabel bevat de algemene functies die zijn opgenomen in de WinINet-functies. De algemene functies kunnen worden gebruikt voor verschillende typen ACHTERNET ingangen of kunnen worden gebruikt tijdens verschillende soorten sessies.

Functie Beschrijving
InternetFindNextFile- Hiermee gaat u verder met het inventariseren van bestanden of zoeken. Hiervoor is een ingang vereist die is gemaakt door de ftpFindFirstFile-of internetOpenUrl- functie.
InternetLockRequestFile Hiermee kan de gebruiker een vergrendeling plaatsen op het bestand dat wordt gebruikt. Voor deze functie is een ingang vereist die wordt geretourneerd door de FtpOpenFile-, HttpOpenRequestof InternetOpenUrl--functie.
InternetQueryDataAvailable Hiermee haalt u de hoeveelheid beschikbare gegevens op. Hiervoor is een ingang vereist die is gemaakt door de ftpOpenFile-of httpOpenRequest functie.
InternetQueryOption- Hiermee haalt u de instelling van een internetoptie op.
InternetReadFile- Leest URL-gegevens. Hiervoor is een ingang vereist die is gemaakt door de InternetOpenUrl-, ftpOpenFile-of httpOpenRequest-functie.
InternetSetFilePointer- Hiermee stelt u de positie in voor de volgende leesbewerking in een bestand. Hiervoor is een ingang vereist die is gemaakt door InternetOpenUrl- (alleen op een HTTP-URL) of een ingang die is gemaakt door HttpOpenRequest met behulp van het GET HTTP-werkwoord.
InternetSetOption- Hiermee stelt u een internetoptie in.
InternetSetStatusCallback- Hiermee stelt u een callback-functie in die statusinformatie ontvangt. Wijst een callback-functie toe aan de aangewezen ACHTERNET ingang en alle grepen die ermee zijn afgeleid.
InternetUnlockRequestFile Ontgrendelt een bestand dat is vergrendeld met behulp van de functie InternetLockRequestFile.

 

Het lezen van bestanden, het vinden van het volgende bestand, het bewerken van opties en het instellen van asynchrone bewerkingen zijn gebruikelijk voor de functies die verschillende protocollen ondersteunen en ACHTERNET handletypen.

Bestanden lezen

De functie InternetReadFile wordt gebruikt om resources te downloaden van een ACHTERNET--handle die wordt geretourneerd door de InternetOpenUrl-, FtpOpenFile-of functie HttpOpenRequest.

InternetReadFile accepteert een ongeldige aanwijzervariabele die het adres van een buffer bevat en een aanwijzer naar een variabele die de lengte van de buffer bevat. De functie retourneert de gegevens in de buffer en de hoeveelheid gegevens die in de buffer zijn gedownload.

De WinINet-functies bieden twee technieken om een volledige resource te downloaden:

InternetQueryDataAvailable gebruikt de handle die is gemaakt door InternetOpenUrl, FtpOpenFileof HttpOpenRequest (nadat HttpSendRequest is aangeroepen) en het aantal beschikbare bytes retourneert. De toepassing moet een buffer toewijzen die gelijk is aan het aantal beschikbare bytes, plus 1 voor het afsluitende null- teken en die buffer gebruiken met InternetReadFile-. Deze methode werkt niet altijd omdat InternetQueryDataAvailable de bestandsgrootte controleert die wordt vermeld in de header en niet het werkelijke bestand. De informatie in het headerbestand kan verouderd zijn of het headerbestand ontbreekt, omdat het momenteel niet vereist is volgens alle standaarden.

In het volgende voorbeeld wordt de inhoud van de resource gelezen die wordt geopend door de hResource-ingang en weergegeven in het invoervak dat wordt aangegeven door intCtrlID.

int WINAPI Dumper(HWND hX, int intCtrlID, HINTERNET hResource)
{
    LPTSTR    lpszData;           // buffer for the data
    DWORD     dwSize;             // size of the data available
    DWORD     dwDownloaded;       // size of the downloaded data
    DWORD     dwSizeSum=0;        // size of the data in the text box
    LPTSTR    lpszHolding;        // buffer to merge the text box 
                                  // data and buffer

    // Set the cursor to an hourglass.
    SetCursor(LoadCursor(NULL,IDC_WAIT));

    // This loop handles reading the data.  
    do
    {
        // The call to InternetQueryDataAvailable determines the
        // amount of data available to download.
        if (!InternetQueryDataAvailable(hResource,&dwSize,0,0))
        {
            ErrorOut(hX,GetLastError(),TEXT("InternetReadFile"));
            SetCursor(LoadCursor(NULL,IDC_ARROW));
            return FALSE;
        }
        else
        {    
            // Allocate a buffer of the size returned by
            // InternetQueryDataAvailable.
            lpszData = new TCHAR[dwSize+1];

            // Read the data from the HINTERNET handle.
            if(!InternetReadFile(hResource,(LPVOID)lpszData,
                                 dwSize,&dwDownloaded))
            {
                ErrorOut(hX,GetLastError(),TEXT("InternetReadFile"));
                delete[] lpszData;
                break;
            }
            else
            {
                // Add a null terminator to the end of the 
                // data buffer.
                lpszData[dwDownloaded]='\0';

                // Allocate the holding buffer.
                lpszHolding = new TCHAR[dwSizeSum + dwDownloaded + 1];
                    
                // Check if there has been any data written to 
                // the text box.
                if (dwSizeSum != 0)
                {
                    // Retrieve the data stored in the text 
                    // box, if any.
                    GetDlgItemText(hX,intCtrlID,
                                   (LPTSTR)lpszHolding, 
                                   dwSizeSum);
                         
                    // Add a null terminator at the end of 
                    // the text box data.
                    lpszHolding[dwSizeSum]='\0';
                }
                else
                {
                    // Make the holding buffer an empty string. 
                    lpszHolding[0]='\0';
                }

                size_t cchDest = dwSizeSum + dwDownloaded + 
                                 dwDownloaded + 1;
                LPTSTR pszDestEnd;
                size_t cchRemaining;

                // Add the new data to the holding buffer.
                HRESULT hr = StringCchCatEx(lpszHolding, cchDest, 
                                            lpszData, &pszDestEnd, 
                                            &cchRemaining, 
                                            STRSAFE_NO_TRUNCATION);
                if(SUCCEEDED(hr))
                {
                    // Write the holding buffer to the text box.
                    SetDlgItemText(hX,intCtrlID,(LPTSTR)lpszHolding);

                    // Delete the two buffers.
                    delete[] lpszHolding;
                    delete[] lpszData;

                    // Add the size of the downloaded data to 
                    // the text box data size.
                    dwSizeSum = dwSizeSum + dwDownloaded + 1;

                    // Check the size of the remaining data.  
                    // If it is zero, break.
                    if (dwDownloaded == 0)
                    {
                        break;
                    }                    
                    else
                    {
                        //  Insert error handling code here.
                    }
                }
            }
        }
    }
    while(TRUE);

    // Close the HINTERNET handle.
    InternetCloseHandle(hResource);

    // Set the cursor back to an arrow.
    SetCursor(LoadCursor(NULL,IDC_ARROW));

    // Return.
    return TRUE;
}

InternetReadFile retourneert nul bytes lezen en is voltooid wanneer alle beschikbare gegevens zijn gelezen. Hierdoor kan een toepassing InternetReadFile in een lus gebruiken om de gegevens te downloaden en af te sluiten wanneer er nul bytes worden gelezen en voltooid.

In het volgende voorbeeld wordt de resource van internet gelezen en wordt de resource weergegeven in het invoervak dat wordt aangegeven door intCtrlID. De handle, hInternet, is geretourneerd door InternetOpenUrl, FtpOpenFileof HttpOpenRequest (na verzending door HttpSendRequest).

int WINAPI Dump(HWND hX, int intCtrlID, HINTERNET hResource)
{
     DWORD dwSize = 0;
     LPTSTR lpszData;
     LPTSTR lpszOutPut;
     LPTSTR lpszHolding = TEXT("");
     int nCounter = 1;
     int nBufferSize = 0;
     DWORD BigSize = 8000;

     // Set the cursor to an hourglass.
     SetCursor(LoadCursor(NULL,IDC_WAIT));

     // Begin the loop that reads the data.
     do
     {
          // Allocate the buffer.
          lpszData =new TCHAR[BigSize+1];

          // Read the data.
          if(!InternetReadFile(hResource,
                              (LPVOID)lpszData,
                              BigSize,&dwSize))
          {
               ErrorOut(hX,GetLastError(),TEXT("InternetReadFile"));
               delete []lpszData;
               break;
          }
          else
          {
               // Add a null terminator to the end of the buffer.
               lpszData[dwSize]='\0';

               // Check if all of the data has been read.  This should
               // never get called on the first time through the loop.
               if (dwSize == 0)
               {
                    // Write the final data to the text box.
                    SetDlgItemText(hX,intCtrlID,lpszHolding);

                    // Delete the existing buffers.
                    delete [] lpszData;
                    delete [] lpszHolding;
                    break;
               }

               // Determine the buffer size to hold the new data and
               // the data already written to the text box (if any).
               nBufferSize = (nCounter*BigSize)+1;

               // Increment the number of buffers read.
               nCounter++;               

               // Allocate the output buffer.
               lpszOutPut = new TCHAR[nBufferSize];

               // Make sure the buffer is not the initial buffer.
               if(nBufferSize != int(BigSize+1))
               {
                    // Copy the data in the holding buffer.
                    StringCchCopy(lpszOutPut,nBufferSize,lpszHolding);
                    // Add error handling code here.

                    // Concatenate the new buffer with the 
                    // output buffer.
                    StringCchCat(lpszOutPut, nBufferSize, lpszData);
                    // Add error handling code here.
     
                    // Delete the holding buffer.
                    delete [] lpszHolding;
               }
               else
               {
                    // Copy the data buffer.
                    StringCchCopy(lpszOutPut, nBufferSize, lpszData);
                    // Add error handling code here.
               }

               // Allocate a holding buffer.
               lpszHolding = new TCHAR[nBufferSize]; 

               // Copy the output buffer into the holding buffer.
               memcpy(lpszHolding,lpszOutPut,nBufferSize);

               // Delete the other buffers.
               delete [] lpszData;
               delete [] lpszOutPut;

          }

     }
     while (TRUE);

     // Close the HINTERNET handle.
     InternetCloseHandle(hResource);

     // Set the cursor back to an arrow.
     SetCursor(LoadCursor(NULL,IDC_ARROW));

     // Return.
     return TRUE;
}

Het volgende bestand zoeken

De functie InternetFindNextFile wordt gebruikt om het volgende bestand te vinden in een bestandszoekopdracht, met behulp van de zoekparameters en ACHTERNET ingang van FtpFindFirstFile, of InternetOpenUrl.

Als u een bestandszoekopdracht wilt voltooien, blijft u InternetFindNextFile aanroepen met behulp van de ACHTERNET- handle die wordt geretourneerd door FtpFindFirstFileof InternetOpenUrl- totdat de functie mislukt met het uitgebreide foutbericht ERROR_NO_MORE_FILES. Als u de uitgebreide foutinformatie wilt ophalen, roept u de functie GetLastError aan.

In het volgende voorbeeld wordt de inhoud van een FTP-map weergegeven in de keuzelijst die wordt aangegeven door lstDirectory. De ACHTERNET ingang, hConnect, is een ingang die wordt geretourneerd door de functie InternetConnect nadat er een FTP-sessie is gemaakt.

bool WINAPI DisplayDir( HWND hX, 
                        int lstDirectory, 
                        HINTERNET hConnect, 
                        DWORD dwFlag )
{
     WIN32_FIND_DATA pDirInfo;
     HINTERNET hDir;
     TCHAR DirList[MAX_PATH];

     // Set the cursor to an hourglass.
     SetCursor(LoadCursor(NULL,IDC_WAIT));

     // Reset the list box.
     SendDlgItemMessage(hX, lstDirectory,LB_RESETCONTENT,0,0);

     // Find the first file.
     hDir = FtpFindFirstFile (hConnect, TEXT ("*.*"), 
                              &pDirInfo, dwFlag, 0);
     if (!hDir)                                     
     {
          // Check if the error was because there were no files.
          if (GetLastError()  == ERROR_NO_MORE_FILES) 
          {
               // Alert user.
               MessageBox(hX, TEXT("There are no files here!!!"), 
                          TEXT("Display Dir"), MB_OK);

               // Close the HINTERNET handle.
               InternetCloseHandle(hDir);

               // Set the cursor back to an arrow.
               SetCursor(LoadCursor(NULL,IDC_ARROW));

               // Return.
               return TRUE;
          }
          else 
          {
               // Call error handler.
               ErrorOut (hX, GetLastError (), TEXT("FindFirst error: "));

               // Close the HINTERNET handle.
               InternetCloseHandle(hDir);

               // Set the cursor back to an arrow.
               SetCursor(LoadCursor(NULL,IDC_ARROW));

               // Return.
               return FALSE;
          }
     }
     else
     {
          // Write the file name to a string.
          StringCchPrintf(DirList, MAX_PATH, pDirInfo.cFileName);

          // Check the type of file.
          if (pDirInfo.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
          {
               // Add <DIR> to indicate that this is 
               // a directory to the user.
               StringCchCat(DirList, MAX_PATH, TEXT(" <DIR> "));
               // Add error handling code here.
          }
       
          // Add the file name (or directory) to the list box.
          SendDlgItemMessage(hX, lstDirectory, LB_ADDSTRING,
                             0, (LPARAM)DirList);
     }
     do
     {
          // Find the next file.
          if (!InternetFindNextFile (hDir, &pDirInfo))
          {
               // Check if there are no more files left. 
               if ( GetLastError() == ERROR_NO_MORE_FILES ) 
               {
                    // Close the HINTERNET handle.
                    InternetCloseHandle(hDir);

                    // Set the cursor back to an arrow.
                    SetCursor(LoadCursor(NULL,IDC_ARROW));

                    // Return.
                    return TRUE;
               }
               else
               {   
                    // Handle the error.
                    ErrorOut (hX, GetLastError(), 
                              TEXT("InternetFindNextFile"));

                    // Close the HINTERNET handle.
                    InternetCloseHandle(hDir);

                    // Set the cursor back to an arrow.
                    SetCursor(LoadCursor(NULL,IDC_ARROW));

                    // Return.
                    return FALSE;
               }
           }
           else
           {
               // Write the file name to a string.
               StringCchPrintf(DirList, MAX_PATH, pDirInfo.cFileName);

               // Check the type of file.
               if(pDirInfo.dwFileAttributes==FILE_ATTRIBUTE_DIRECTORY)
               {
                    // Add <DIR> to indicate that this is a 
                    // directory to the user.
                    StringCchCat(DirList, MAX_PATH, TEXT(" <DIR> "));
                    // Add error handling code here.
               }
     
               // Add the file name (or directory) to the list box.
               SendDlgItemMessage(hX, lstDirectory, LB_ADDSTRING,
                                  0, (LPARAM)DirList);
           }
     }
     while ( TRUE);
     
}

Opties voor bewerken

InternetSetOption- en InternetQueryOption- worden gebruikt om de WinINet-opties te bewerken.

InternetSetOption- accepteert een variabele die aangeeft welke optie moet worden ingesteld, een buffer voor de instelling van de optie en een aanwijzer die het adres bevat van de variabele die de lengte van de buffer bevat.

InternetQueryOption- accepteert een variabele die de optie aangeeft die moet worden opgehaald, een buffer voor het opslaan van de optie-instelling en een aanwijzer die het adres bevat van de variabele die de lengte van de buffer bevat.

Asynchrone bewerkingen instellen

De WinINet-functies werken standaard synchroon. Een toepassing kan asynchrone bewerking aanvragen door de vlag INTERNET_FLAG_ASYNC in te stellen in de aanroep van de functie InternetOpen. Alle toekomstige aanroepen op basis van ingangen die zijn afgeleid van de ingang die door InternetOpen worden geretourneerd, worden asynchroon uitgevoerd.

De reden voor asynchrone versus synchrone bewerking is om een toepassing met één thread het gebruik van de CPU te maximaliseren zonder te hoeven wachten tot de netwerk-I/O is voltooid. Afhankelijk van de aanvraag kan de bewerking daarom synchroon of asynchroon worden voltooid. De toepassing moet de retourcode controleren. Als een functie FALSE of NULL-retourneert en GetLastError ERROR_IO_PENDING retourneert, is de aanvraag asynchroon uitgevoerd en wordt de toepassing teruggeroepen met INTERNET_STATUS_REQUEST_COMPLETE wanneer de functie is voltooid.

Als u een asynchrone bewerking wilt starten, moet de toepassing de vlag INTERNET_FLAG_ASYNC instellen in de aanroep naar InternetOpen. De toepassing moet vervolgens een geldige callback-functie registreren met behulp van InternetSetStatusCallback-.

Nadat een callback-functie is geregistreerd voor een ingang, kunnen alle bewerkingen op die ingang statusindicaties genereren, mits de contextwaarde die is opgegeven toen de handle werd gemaakt, niet nul was. Als u een nulcontextwaarde opgeeft, wordt een bewerking synchroon voltooid, ook al is INTERNET_FLAG_ASYNC opgegeven in InternetOpen.

Statusindicaties geven de toepassing feedback over de voortgang van netwerkbewerkingen, zoals het omzetten van een hostnaam, het maken van verbinding met een server en het ontvangen van gegevens. Er kunnen drie speciale statusaanduidingen worden gemaakt voor een ingang:

  • INTERNET_STATUS_HANDLE_CLOSING is de laatste statusindicatie die is gemaakt voor een ingang.
  • INTERNET_STATUS_HANDLE_CREATED geeft aan wanneer de ingang in eerste instantie wordt gemaakt.
  • INTERNET_STATUS_REQUEST_COMPLETE geeft aan dat een asynchrone bewerking is voltooid.

De toepassing moet de INTERNET_ASYNC_RESULT structuur controleren om te bepalen of de bewerking is geslaagd of mislukt na ontvangst van een INTERNET_STATUS_REQUEST_COMPLETE indicatie.

In het volgende voorbeeld ziet u een voorbeeld van een callback-functie en een aanroep naar InternetSetStatusCallback- om de functie te registreren als de callback-functie.

void CALLBACK InternetCallback(
    HINTERNET hInternet,
    DWORD_PTR dwcontext,
    DWORD dwInternetStatus,
    LPVOID lpvStatusInformation,
    DWORD dwStatusInformationLength
    )
{
    _tprintf(TEXT("%0xd %0xp %0xd %0xp %0xd\n"),
             hInternet,
             dwcontext,
             dwInternetStatus,
             lpvStatusInformation,
             dwStatusInformationLength);
};

INTERNET_STATUS_CALLBACK dwISC =
    InternetSetStatusCallback(hInternet, InternetCallback); 

ACHTERNET-ingangen sluiten

Alle ACHTERNET- ingangen kunnen worden gesloten met behulp van de functie InternetCloseHandle. Clienttoepassingen moeten alle ACHTERNET- ingangen sluiten die zijn afgeleid van de ACHTERNET- ingang die ze proberen te sluiten voordat ze InternetCloseHandle- op de ingang aanroepen.

In het volgende voorbeeld ziet u de hiërarchie van ingangen.

HINTERNET hRootHandle, hOpenUrlHandle;

hRootHandle = InternetOpen( TEXT("Example"), 
                            INTERNET_OPEN_TYPE_DIRECT, 
                            NULL, 
                            NULL, 0);

hOpenUrlHandle = InternetOpenUrl(hRootHandle, 
    TEXT("https://www.server.com/default.htm"), NULL, 0, 
    INTERNET_FLAG_RAW_DATA,0);

// Close the handle created by InternetOpenUrl so that the
// InternetOpen handle can be closed.
InternetCloseHandle(hOpenUrlHandle); 

// Close the handle created by InternetOpen.
InternetCloseHandle(hRootHandle);

Resources vergrendelen en ontgrendelen

Met de functie InternetLockRequestFile kan een toepassing ervoor zorgen dat de resource in de cache die is gekoppeld aan de ACHTERNET- ingang die eraan wordt doorgegeven, niet uit de cache verdwijnt. Als een andere download probeert een resource met dezelfde URL als het vergrendelde bestand door te voeren, voorkomt de cache dat het bestand wordt verwijderd door een veilige verwijdering uit te voeren. Nadat de toepassing de functie InternetUnlockRequestFile aanroept, krijgt de cache toestemming om het bestand te verwijderen.

Als de vlag INTERNET_FLAG_NO_CACHE_WRITE of INTERNET_FLAG_DONT_CACHE is ingesteld, maakt InternetLockRequestFile een tijdelijk bestand met de extensie TMP, tenzij de ingang is verbonden met een https-resource. Als de functie toegang heeft tot een https-resource en INTERNET_FLAG_NO_CACHE_WRITE (of INTERNET_FLAG_DONT_CACHE) is ingesteld, mislukt InternetLockRequestFile-.

Notitie

WinINet biedt geen ondersteuning voor serverimplementaties. Daarnaast mag deze niet worden gebruikt vanuit een service. Voor server-implementaties of -services wordt Microsoft Windows HTTP Services (WinHTTP)gebruikt.