Fonctions courantes (Windows Internet)
Les différents protocoles Internet (tels que ftp et http) utilisent plusieurs des mêmes fonctions WinINet pour gérer les informations sur Internet. Ces fonctions courantes gèrent leurs tâches de manière cohérente, quel que soit le protocole particulier auquel ils sont appliqués. Les applications peuvent utiliser ces fonctions pour créer des fonctions à usage général qui gèrent des tâches sur les différents protocoles (par exemple, la lecture de fichiers pour ftp et http).
Les fonctions courantes gèrent les tâches suivantes :
- Téléchargement de ressources à partir d’Internet (internetReadFile, InternetSetFilePointer, InternetFindNextFileet InternetQueryDataAvailable).
- Configuration d’opérations asynchrones (InternetSetStatusCallback).
- Affichage et modification des options (InternetSetOption et InternetQueryOption).
- Fermeture de tous les types de handles HINTERNET (InternetCloseHandle).
- Placement et suppression de verrous sur des ressources (InternetLockRequestFile et InternetUnlockRequestFile).
Utilisation de fonctions courantes
Le tableau suivant répertorie les fonctions courantes incluses dans les fonctions WinINet. Les fonctions courantes peuvent être utilisées sur différents types de handles HINTERNET ou peuvent être utilisées pendant différents types de sessions.
Fonction | Description |
---|---|
InternetFindNextFile | Poursuit l’énumération ou la recherche de fichiers. Nécessite un handle créé par la fonction FtpFindFirstFile, ou fonction InternetOpenUrl. |
internetLockRequestFile | Permet à l’utilisateur de placer un verrou sur le fichier utilisé. Cette fonction nécessite un handle retourné par la fonction FtpOpenFile, HttpOpenRequestou fonction InternetOpenUrl. |
internetQueryDataAvailable | Récupère la quantité de données disponibles. Nécessite un handle créé par leftpOpenFile, ou fonction HttpOpenRequest. |
InternetQueryOption | Récupère le paramètre d’une option Internet. |
internetReadFile | Lit les données d’URL. Nécessite un handle créé par leInternetOpenUrl, ftpOpenFileou fonction HttpOpenRequest. |
internetSetFilePointer | Définit la position de la lecture suivante dans un fichier. Nécessite un handle créé par InternetOpenUrl (sur une URL HTTP uniquement) ou un handle créé par HttpOpenRequest à l’aide du verbe GET HTTP. |
internetSetOption | Définit une option Internet. |
internetSetStatusCallback | Définit une fonction de rappel qui reçoit des informations d’état. Affecte une fonction de rappel au handleHINTERNET désigné et à tous les handles dérivés de celui-ci. |
internetUnlockRequestFile | Déverrouille un fichier verrouillé à l’aide de la fonction InternetLockRequestFile. |
La lecture de fichiers, la recherche du fichier suivant, la manipulation d’options et la configuration d’opérations asynchrones sont communes aux fonctions qui prennent en charge différents protocoles et HINTERNET de gérer les types.
Lecture de fichiers
La fonctionInternetReadFile est utilisée pour télécharger des ressources à partir d’un handle HINTERNET retourné par la fonctionInternetOpenUrl, FtpOpenFileou fonction HttpOpenRequest.
InternetReadFile accepte une variable de pointeur void qui contient l’adresse d’une mémoire tampon et un pointeur vers une variable qui contient la longueur de la mémoire tampon. La fonction retourne les données dans la mémoire tampon et la quantité de données téléchargées dans la mémoire tampon.
Les fonctions WinINet fournissent deux techniques pour télécharger une ressource entière :
- Fonction InternetQueryDataAvailable.
- Valeurs de retour de InternetReadFile .
InternetQueryDataAvailable prend le handle HINTERNET créé par internetOpenUrl, FtpOpenFile, ou HttpOpenRequest (après HttpSendRequest a été appelé sur le handle) et retourne le nombre d’octets disponibles. L’application doit allouer une mémoire tampon égale au nombre d’octets disponibles, plus 1 pour la fin caractère de null et utiliser cette mémoire tampon avec InternetReadFile. Cette méthode ne fonctionne pas toujours, car InternetQueryDataAvailable vérifie la taille de fichier répertoriée dans l’en-tête et non le fichier réel. Les informations contenues dans le fichier d’en-tête peuvent être obsolètes ou le fichier d’en-tête peut être manquant, car il n’est pas actuellement requis dans toutes les normes.
L’exemple suivant lit le contenu de la ressource accessible par le handle hResource et s’affiche dans la zone d’édition indiquée par 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 renvoie zéro octets lus et se termine correctement lorsque toutes les données disponibles ont été lues. Cela permet à une application d’utiliser internetReadFile dans une boucle pour télécharger les données et quitter lorsqu’elle retourne zéro octets lu et se termine correctement.
L’exemple suivant lit la ressource à partir d’Internet et affiche la ressource dans la zone d’édition indiquée par intCtrlID. Le handleHINTERNET, hInternet, a été retourné par InternetOpenUrl, FtpOpenFileou httpOpenRequest (après avoir été envoyé par 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;
}
Recherche du fichier suivant
La fonction InternetFindNextFile permet de rechercher le fichier suivant dans une recherche de fichiers, en utilisant les paramètres de recherche et handle HINTERNET de FtpFindFirstFile, ou InternetOpenUrl.
Pour effectuer une recherche de fichiers, continuez à appeler InternetFindNextFile à l’aide du handle HINTERNET retourné par FtpFindFirstFile, ou InternetOpenUrl jusqu’à ce que la fonction échoue avec le message d’erreur étendu ERROR_NO_MORE_FILES. Pour obtenir les informations d’erreur étendues, appelez la fonction GetLastError.
L’exemple suivant affiche le contenu d’un répertoire FTP dans la zone de liste indiquée par lstDirectory. Le handle HINTERNET, hConnect, est un handle retourné par la fonction InternetConnect après avoir établi une session FTP.
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);
}
Manipulation d’options
internetSetOption et internetQueryOption sont utilisés pour manipuler les options WinINet.
InternetSetOption accepte une variable qui indique l’option à définir, une mémoire tampon pour contenir le paramètre d’option et un pointeur qui contient l’adresse de la variable qui contient la longueur de la mémoire tampon.
InternetQueryOption accepte une variable qui indique l’option à récupérer, une mémoire tampon pour contenir le paramètre d’option et un pointeur qui contient l’adresse de la variable qui contient la longueur de la mémoire tampon.
Configuration d’opérations asynchrones
Par défaut, les fonctions WinINet fonctionnent de manière synchrone. Une application peut demander une opération asynchrone en définissant l’indicateur INTERNET_FLAG_ASYNC dans l’appel à la fonction InternetOpen. Tous les appels futurs effectués par rapport aux handles dérivés du handle retourné par InternetOpen sont effectués de manière asynchrone.
La justification de l’opération asynchrone et synchrone consiste à permettre à une application monothread d’optimiser son utilisation du processeur sans avoir à attendre que les E/S réseau se terminent. Par conséquent, en fonction de la demande, l’opération peut se terminer de manière synchrone ou asynchrone. L’application doit vérifier le code de retour. Si une fonction retourne FALSE ou NULL, et GetLastError retourne ERROR_IO_PENDING, la requête a été effectuée de manière asynchrone et l’application est renvoyée avec INTERNET_STATUS_REQUEST_COMPLETE une fois la fonction terminée.
Pour commencer l’opération asynchrone, l’application doit définir l’indicateur INTERNET_FLAG_ASYNC dans son appel à InternetOpen. L’application doit ensuite inscrire une fonction de rappel valide, à l’aide de InternetSetStatusCallback.
Une fois qu’une fonction de rappel est inscrite pour un handle, toutes les opérations sur ce handle peuvent générer des indications d’état, à condition que la valeur de contexte fournie lors de la création du handle n’ait pas été zéro. Fournir une valeur de contexte zéro force une opération à se terminer de manière synchrone, même si INTERNET_FLAG_ASYNC a été spécifiée dans InternetOpen.
Les indications d’état fournissent des commentaires sur la progression des opérations réseau, telles que la résolution d’un nom d’hôte, la connexion à un serveur et la réception de données. Trois indications d’état à usage spécial peuvent être faites pour un handle :
- INTERNET_STATUS_HANDLE_CLOSING est la dernière indication d’état qui est faite pour un handle.
- INTERNET_STATUS_HANDLE_CREATED indique quand le handle est initialement créé.
- INTERNET_STATUS_REQUEST_COMPLETE indique qu’une opération asynchrone est terminée.
L’application doit vérifier la structure INTERNET_ASYNC_RESULT pour déterminer si l’opération a réussi ou échoué après avoir reçu une indication INTERNET_STATUS_REQUEST_COMPLETE.
L’exemple suivant montre un exemple de fonction de rappel et un appel à InternetSetStatusCallback pour inscrire la fonction en tant que fonction de rappel.
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);
Handles HINTERNET fermants
Tous les handles HINTERNET peuvent être fermés à l’aide de la fonctionInternetCloseHandle. Les applications clientes doivent fermer tous les handles HINTERNET dérivés du handle HINTERNET qu’ils essaient de fermer avant d’appeler InternetCloseHandle sur le handle.
L’exemple suivant illustre la hiérarchie de handles.
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);
Verrouillage et déverrouillage des ressources
La fonctionInternetLockRequestFile permet à une application de s’assurer que la ressource mise en cache associée au handle HINTERNET transmis ne disparaît pas du cache. Si un autre téléchargement tente de valider une ressource ayant la même URL que le fichier verrouillé, le cache évite de supprimer le fichier en effectuant une suppression sécurisée. Une fois que l’application appelle la fonctioninternetUnlockRequestFile, le cache est autorisé à supprimer le fichier.
Si l’indicateur INTERNET_FLAG_NO_CACHE_WRITE ou INTERNET_FLAG_DONT_CACHE a été défini, InternetLockRequestFile crée un fichier temporaire avec l’extension TMP, sauf si le handle est connecté à une ressource https. Si la fonction accède à une ressource https et INTERNET_FLAG_NO_CACHE_WRITE (ou INTERNET_FLAG_DONT_CACHE) a été définie, InternetLockRequestFile échoue.
Note
WinINet ne prend pas en charge les implémentations de serveur. En outre, il ne doit pas être utilisé à partir d’un service. Pour les implémentations de serveur ou les services, utilisez Microsoft Windows HTTP Services (WinHTTP).