Allgemeine Funktionen (Windows Internet)

Die verschiedenen Internetprotokolle (z. B. ftp und http) verwenden mehrere der gleichen WinINet-Funktionen, um Informationen im Internet zu verarbeiten. Diese allgemeinen Funktionen verarbeiten ihre Aufgaben auf konsistente Weise, unabhängig vom jeweiligen Protokoll, auf das sie angewendet werden. Anwendungen können diese Funktionen verwenden, um allgemeine Funktionen zu erstellen, die Aufgaben in den verschiedenen Protokollen verarbeiten (z. B. das Lesen von Dateien für FTP und HTTP).

Die allgemeinen Funktionen behandeln die folgenden Aufgaben:

Verwenden von allgemeinen Funktionen

In der folgenden Tabelle sind die allgemeinen Funktionen aufgeführt, die in den WinINet-Funktionen enthalten sind. Die allgemeinen Funktionen können für verschiedene Typen von HINTERNET-Handles oder während verschiedener Sitzungstypen verwendet werden.

Funktion BESCHREIBUNG
InternetFindNextFile Setzt die Dateiaufzählung oder Suche fort. Erfordert ein Handle, das von der FtpFindFirstFile- oder InternetOpenUrl-Funktion erstellt wurde.
InternetLockRequestFile Ermöglicht dem Benutzer, eine Sperre für die verwendete Datei zu platzieren. Diese Funktion erfordert ein Handle, das von der FtpOpenFile-, HttpOpenRequest- oder InternetOpenUrl-Funktion zurückgegeben wird.
InternetQueryDataAvailable Ruft die verfügbare Datenmenge ab. Erfordert ein Handle, das von der FtpOpenFile- oder HttpOpenRequest-Funktion erstellt wurde.
InternetQueryOption Ruft die Einstellung einer Internetoption ab.
InternetReadFile Liest URL-Daten. Erfordert ein Handle, das von der Funktion InternetOpenUrl, FtpOpenFile oder HttpOpenRequest erstellt wurde.
InternetSetFilePointer Legt die Position für den nächsten Lesevorgang in einer Datei fest. Erfordert ein von InternetOpenUrl erstelltes Handle (nur für eine HTTP-URL) oder ein Handle, das von HttpOpenRequest mit dem GET-HTTP-Verb erstellt wurde.
InternetSetOption Legt eine Internetoption fest.
InternetSetStatusCallback Legt eine Rückruffunktion fest, die status Informationen empfängt. Weist dem angegebenen HINTERNET-Handle und allen daraus abgeleiteten Handles eine Rückruffunktion zu.
InternetUnlockRequestFile Entsperrt eine Datei, die mit der InternetLockRequestFile-Funktion gesperrt wurde.

 

Das Lesen von Dateien, das Suchen der nächsten Datei, das Bearbeiten von Optionen und das Einrichten asynchroner Vorgänge sind für die Funktionen üblich, die verschiedene Protokolle und HINTERNET-Handletypen unterstützen.

Lesen von Dateien

Die InternetReadFile-Funktion wird verwendet, um Ressourcen aus einem HINTERNET-Handle herunterzuladen, das von der InternetOpenUrl-, FtpOpenFile- oder HttpOpenRequest-Funktion zurückgegeben wird.

InternetReadFile akzeptiert eine void-Zeigervariable, die die Adresse eines Puffers und einen Zeiger auf eine Variable enthält, die die Länge des Puffers enthält. Die Funktion gibt die Daten im Puffer und die Menge der in den Puffer heruntergeladenen Daten zurück.

Die WinINet-Funktionen bieten zwei Techniken zum Herunterladen einer gesamten Ressource:

InternetQueryDataAvailable verwendet das von InternetOpenUrl, FtpOpenFile oder HttpOpenRequest erstellte HINTERNET-Handle (nachdem HttpSendRequest für das Handle aufgerufen wurde) und gibt die Anzahl der verfügbaren Bytes zurück. Die Anwendung sollte einen Puffer zuordnen, der der Anzahl der verfügbaren Bytes entspricht, plus 1 für das abschließende NULL-Zeichen , und diesen Puffer mit InternetReadFile verwenden. Diese Methode funktioniert nicht immer, da InternetQueryDataAvailable die im Header aufgeführte Dateigröße und nicht die tatsächliche Datei überprüft. Die Informationen in der Headerdatei sind möglicherweise veraltet, oder die Headerdatei fehlt, da sie derzeit nicht unter allen Standards erforderlich ist.

Im folgenden Beispiel wird der Inhalt der Ressource gelesen, auf die über das hResource-Handle zugegriffen und im Bearbeitungsfeld angezeigt wird, das durch intCtrlID angegeben ist.

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 gibt null Bytes zurück und schließt erfolgreich ab, wenn alle verfügbaren Daten gelesen wurden. Dadurch kann eine Anwendung InternetReadFile in einer Schleife verwenden, um die Daten herunterzuladen und zu beenden, wenn null Bytes gelesen und erfolgreich abgeschlossen werden.

Im folgenden Beispiel wird die Ressource aus dem Internet gelesen und die Ressource im Bearbeitungsfeld angezeigt, das durch intCtrlID angegeben ist. Das HINTERNET-Handle hInternet wurde von InternetOpenUrl, FtpOpenFile oder HttpOpenRequest (nach dem Senden von HttpSendRequest) zurückgegeben.

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

Suchen der nächsten Datei

Die InternetFindNextFile-Funktion wird verwendet, um die nächste Datei in einer Dateisuche zu finden, wobei die Suchparameter und das HINTERNET-Handle von FtpFindFirstFile oder InternetOpenUrl verwendet werden.

Um eine Dateisuche abzuschließen, rufen Sie internetFindNextFile mit dem von FtpFindFirstFile zurückgegebenen HINTERNET-Handle oder InternetOpenUrl auf, bis die Funktion mit der erweiterten Fehlermeldung ERROR_NO_MORE_FILES fehlschlägt. Rufen Sie die GetLastError-Funktion auf, um die erweiterten Fehlerinformationen abzurufen.

Im folgenden Beispiel wird der Inhalt eines FTP-Verzeichnisses im Durch lstDirectory angegebenen Listenfeld angezeigt. Das HINTERNET-Handle hConnect ist ein Handle, das von der InternetConnect-Funktion zurückgegeben wird, nachdem eine FTP-Sitzung eingerichtet wurde.

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

Bearbeiten von Optionen

InternetSetOption und InternetQueryOption werden verwendet, um die WinINet-Optionen zu bearbeiten.

InternetSetOption akzeptiert eine Variable, die die festzulegende Option angibt, einen Puffer, der die Optionseinstellung enthält, und einen Zeiger, der die Adresse der Variablen enthält, die die Länge des Puffers enthält.

InternetQueryOption akzeptiert eine Variable, die die abzurufende Option angibt, einen Puffer, der die Optionseinstellung enthält, und einen Zeiger, der die Adresse der Variablen enthält, die die Länge des Puffers enthält.

Einrichten asynchroner Vorgänge

Standardmäßig werden die WinINet-Funktionen synchron ausgeführt. Eine Anwendung kann einen asynchronen Vorgang anfordern, indem das INTERNET_FLAG_ASYNC-Flag im Aufruf der InternetOpen-Funktion festgelegt wird. Alle zukünftigen Aufrufe für Handles, die vom von InternetOpen zurückgegebenen Handle abgeleitet werden, werden asynchron ausgeführt.

Der Grund für asynchronen und synchronen Betrieb besteht darin, einer Singlethread-Anwendung die Maximierung der CPU-Auslastung zu ermöglichen, ohne auf den Abschluss der Netzwerk-E/A warten zu müssen. Daher kann der Vorgang je nach Anforderung synchron oder asynchron abgeschlossen werden. Die Anwendung sollte den Rückgabecode überprüfen. Wenn eine Funktion FALSE oder NULL zurückgibt und GetLastError ERROR_IO_PENDING zurückgibt, wurde die Anforderung asynchron durchgeführt, und die Anwendung wird mit INTERNET_STATUS_REQUEST_COMPLETE zurückgerufen, wenn die Funktion abgeschlossen ist.

Um mit dem asynchronen Vorgang zu beginnen, muss die Anwendung das flag INTERNET_FLAG_ASYNC in ihrem Aufruf von InternetOpen festlegen. Die Anwendung muss dann mithilfe von InternetSetStatusCallback eine gültige Rückruffunktion registrieren.

Nachdem eine Rückruffunktion für ein Handle registriert wurde, können alle Vorgänge für dieses Handle status Hinweise generieren, vorausgesetzt, der kontextbezogene Wert, der bei der Erstellung des Handles angegeben wurde, war nicht null. Die Angabe eines Nullkontextwerts erzwingt, dass ein Vorgang synchron abgeschlossen wird, obwohl INTERNET_FLAG_ASYNC in InternetOpen angegeben wurde.

Statusanzeigen geben der Anwendung Feedback zum Fortschritt von Netzwerkvorgängen, z. B. auflösen eines Hostnamens, Herstellen einer Verbindung mit einem Server und Empfangen von Daten. Für einen Griff können drei spezielle status Hinweise gemacht werden:

  • INTERNET_STATUS_HANDLE_CLOSING ist der letzte status Hinweis, der für einen Handle erstellt wurde.
  • INTERNET_STATUS_HANDLE_CREATED gibt an, wann das Handle ursprünglich erstellt wird.
  • INTERNET_STATUS_REQUEST_COMPLETE gibt an, dass ein asynchroner Vorgang abgeschlossen wurde.

Die Anwendung muss die INTERNET_ASYNC_RESULT Struktur überprüfen, um festzustellen, ob der Vorgang erfolgreich war oder fehlgeschlagen ist, nachdem eine INTERNET_STATUS_REQUEST_COMPLETE-Anzeige empfangen wurde.

Das folgende Beispiel zeigt ein Beispiel für eine Rückruffunktion und einen Aufruf von InternetSetStatusCallback , um die Funktion als Rückruffunktion zu registrieren.

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

Schließen von HINTERNET-Handles

Alle HINTERNET-Handles können mithilfe der InternetCloseHandle-Funktion geschlossen werden. Clientanwendungen müssen alle HINTERNET-Handles schließen, die vom HINTERNET-Handle abgeleitet sind, das sie schließen möchten, bevor InternetCloseHandle für das Handle aufgerufen wird.

Im folgenden Beispiel wird die Handlehierarchie veranschaulicht.

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

Sperren und Entsperren von Ressourcen

Mit der InternetLockRequestFile-Funktion kann eine Anwendung sicherstellen, dass die zwischengespeicherte Ressource, die dem an sie übergebenen HINTERNET-Handle zugeordnet ist, nicht aus dem Cache verschwindet. Wenn ein anderer Download versucht, eine Ressource mit derselben URL wie die gesperrte Datei zu committen, vermeidet der Cache das Entfernen der Datei durch einen sicheren Löschvorgang. Nachdem die Anwendung die InternetUnlockRequestFile-Funktion aufgerufen hat, erhält der Cache die Berechtigung zum Löschen der Datei.

Wenn das INTERNET_FLAG_NO_CACHE_WRITE - oder INTERNET_FLAG_DONT_CACHE-Flag festgelegt wurde, erstellt InternetLockRequestFile eine temporäre Datei mit der Erweiterung TMP, es sei denn, das Handle ist mit einer HTTPS-Ressource verbunden. Wenn die Funktion auf eine HTTPS-Ressource zugreift und INTERNET_FLAG_NO_CACHE_WRITE (oder INTERNET_FLAG_DONT_CACHE) festgelegt wurde, schlägt InternetLockRequestFile fehl.

Hinweis

WinINet unterstützt keine Serverimplementierungen. Darüber hinaus sollte es nicht von einem Dienst verwendet werden. Verwenden Sie für Serverimplementierungen oder Dienste Microsoft Windows HTTP Services (WinHTTP).