IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo
Sommaire > ISAPI
        Comment renvoyer du binaire dans un flux http depuis une DLL d'extension server (IIS) ISAPI ?
        Comment renvoyer une ressource binaire dans un flux http depuis une DLL d'extension server (IIS) ISAPI ?
        Comment traduire une requête envoyée en séquence Escape dans une DLL d'extension server (IIS) ISAPI ?
        Comment utiliser ADO dans une DLL d'extension server (IIS) ISAPI ?
        Comment ajouter une fonction appelable par http dans une DLL d'extension server ISAPI ?
        Comment récupérer l'adresse IP (et autres infos) du poste client qui fait une requête HTTP sur ma DLL Extension ISAPI ?
        Comment redéfinir la fonction par défaut d'une DLL ISAPI ?
        Comment Débugger une DLL ISAPI ?



Comment renvoyer du binaire dans un flux http depuis une DLL d'extension server (IIS) ISAPI ?
Créé le 04/04/2005[haut]
auteur : matazz
En définissant l'opérateur de flux pour un BYTE dans une classe:

// BinaryHtmlStream.h: interface for the CBinaryHtmlStream class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_BINARYHTMLSTREAM_H__E8E5B559_A8D3_4DEE_B38D_2ABF4D319672__INCLUDED_)
#define AFX_BINARYHTMLSTREAM_H__E8E5B559_A8D3_4DEE_B38D_2ABF4D319672__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CBinaryHtmlStream : public CHtmlStream
{
public:
// we have a special overload of << to allow for a single byte
CBinaryHtmlStream& operator<<(BYTE b) { Write(&b, 1); return *this; }
};

#endif // !defined BINHTMSTREAM_H

Comment renvoyer une ressource binaire dans un flux http depuis une DLL d'extension server (IIS) ISAPI ?
Créé le 04/04/2005[haut]
auteur : matazz
En utilisant la classe CBinaryHtmlStream ci-dessus :

//*******************************************************************
// Renvoi une resource du workspace
//*******************************************************************
void ClsMyServerExtension::SendResource(CHttpServerContext *pCtxt, int ID_RS)
{
CBinaryHtmlStream* pStream = new CBinaryHtmlStream();
CString ContentSize;
CString RSNumb;
unsigned int Size = 0;
HINSTANCE hIn= NULL;
HRSRC tSrc= NULL;
HGLOBAL hImage= NULL;
BYTE* pImage= NULL;

     //Attention ajouter le type mime du flux de retour en fonction du type de Resource A modifier
AddHeader(pCtxt ,_T("Content-Type: image/jpeg\r\n"));}
     //AddHeader(pCtxt ,_T("Content-Type: application/x-shockwave-flash\r\n"));}

RSNumb.Format("#%d",ID_RS);

hIn= AfxGetResourceHandle();
     // BINARY est un groupe de resource comme Dialog, Menu...
tSrc= ::FindResource (hIn,RSNumb.GetBuffer(0),"BINARY");
hImage= ::LoadResource(hIn,tSrc);
Size= ::SizeofResource(hIn,tSrc);
pImage= (BYTE*) ::LockResource(hImage);

ContentSize.Format( "Content-length: %d\r\n", Size);
AddHeader( pCtxt ,_T(ContentSize));

for (int Ind = 0; Ind <Size; Ind++){*pStream << pImage[Ind];}

*pCtxt << *pStream;
delete pStream;
//delete pImage; Supprimé à la destruction du Thread(Voire MSDN) 
}

Comment traduire une requête envoyée en séquence Escape dans une DLL d'extension server (IIS) ISAPI ?
Créé le 04/04/2005[haut]
auteur : matazz
La séquence Escape c'est une forme de codage des caractères non alpha-numérique du style "-1" en Séquence Escape sera "%2D1". En gros c'est % + code Hexa du car.

Le problème c'est que si Dans une DLL extension ISAPI vous définissez une fonction comme suite :

ON_PARSE_COMMAND(Reload, ClsMyServerExtension, ITS_PSTR ITS_R4 )
ON_PARSE_COMMAND_PARAMS("String=Str Double=-1.54")
Si vous appelez votre DLL comme suit : http://www.monsite.com/Scripts/MyServerExtension.dll?Reload&String=toto&Double=%2D25%2E12
où %2D25%2E12 correspond à -25.12.
Vous recevrez dans la DLL comme valeur de Double 25.00 et non -25.12

Pou corriger ce bug de IIS :

ON_PARSE_COMMAND(Reload, ClsMyServerExtension, ITS_PSTR ITS_PSTR )
ON_PARSE_COMMAND_PARAMS("String=Str Double=-1.54")
Double devient une String et la séquence Escape sera correctement traduite, charge à vous de faire un atof(...) pour récupérer un double...


Comment utiliser ADO dans une DLL d'extension server (IIS) ISAPI ?
Créé le 04/04/2005[haut]
auteur : matazz
L'environnement IIS (ou 2IS) est MultiThread à savoir que chaque requête Http est parsée puis executée sur un thread (Attention aux variables globales de la classe car tous les thread vont y acceder).
Ainsi si vous voulez utiliser ADO dans une DLL ISAP il faut effectuer le CoInitialize et CoUninitialize dans chaque Function appellable par IIS :

Imaginons que vous ayez deux fonctions appelables depuis une requête http

ON_PARSE_COMMAND(GetRaster, ClsMyServerExtension, ITS_PSTR )
ON_PARSE_COMMAND_PARAMS("D=DataBase")

ON_PARSE_COMMAND(Reload, ClsMyServerExtension, ITS_PSTR)
ON_PARSE_COMMAND_PARAMS("R=r")
Il faudra faire dans chacune des fonctions qui utilisent ADO :

//*******************************************************************
// Recharge la config
//*******************************************************************
void ClsMyServerExtension::Reload(CHttpServerContext *pCtxt, LPTSTR R)
{
HRESULT hres = ::CoInitializeEx(NULL,COINIT_MULTITHREADED );
    ...//traitement plus renvoi de texte ou dat dans le flux...
::CoUninitialize();
}
Pour utiliser le Flag COINIT_MULTITHREADED il faut définir dans le .h de votre extension serveur .

#define _WIN32_DCOM
#include "objbase.h"
Remarque : vous pouvez mettre simplement ::CoInitialize(NULL) mais si vous avez des retours de HTML avec un code du genre -2147417842 (0x8001010e) vous devrez utiliser le flag COINIT_MULTITHREADED.


Comment ajouter une fonction appelable par http dans une DLL d'extension server ISAPI ?
Créé le 04/04/2005[haut]
auteur : matazz
Cela peut paraître trivial comme question, mais c'est pas forcément clair lorsque l'on fait un nouveau workspace en choisissant ISAPI extension Server.

En fait on peut avoir si l'on veut deux types de fonctions :

Les fonctions points d'entrée HTTP et les autres à savoir celles qui vont servir aux fonctions points d'entrée.

Pour la clarté il paraît plus simple de faire une ou plusieurs classes qui réalisent les traitement désirés sur les appels et laisser dans la classe générée par Visual Studio que les fonctions point d'entrées...
Après chacun fait comme il veut...

Donc, pour faire une fonction point d'entrée HTTP il faut faire comme suit :
Ajouter une fonction classiquement mais en mettant toujours comme premier paramètre un pointeur sur un CHttpServerContext :

dans le .h

void GetData(CHttpServerContext *pCtxt, int Integer, LPTSTR String)
et dans le .cpp

void CMyServerExtension::GetData(CHttpServerContext *pCtxt, int Integer, LPTSTR String)
  {
  ...
  }
Ensuite : dans le .cpp (au tout début de ce dernier) il y a une zone définie par :
BEGIN_PARSE_MAP(ClsMyServerExtension, CHttpServer)
Dans cette zone se trouve toutes les données pour que IIS redirige les appels HTTP sur les fonctions de la DLL.
Si vous n'ajoutez pas votre fonction ici vous ne pourrez jamais l'appeller sur une requette HTTP.
Dans notre cas il faut ajouter :

ON_PARSE_COMMAND(GetData, ClsMyServerExtension, ITS_I4 ITS_PSTR)
ON_PARSE_COMMAND_PARAMS("Integer=12 String=MaString")
La première balise correspond à une sorte de prototypage pour IIS et la seconde donne des valeurs par défaut à passer à la fonction si les paramètres ne sont pas présents dans la requette HTTP.

Remarque :
Les types définissables pour le Parse_Command sont :

//pour les fonctions sans paramètres:
#define ITS_EMPTY           "\x06"      // no parameters
//les autres types
#define ITS_I2              "\x01"      // a 'short'
#define ITS_I4              "\x02"      // a 'long'
#define ITS_R4              "\x03"      // a 'float'
#define ITS_R8              "\x04"      // a 'double'
#define ITS_PSTR            "\x05"      // a 'LPCTSTR'
#define ITS_RAW                         "\x07"          // exactly as received

Comment récupérer l'adresse IP (et autres infos) du poste client qui fait une requête HTTP sur ma DLL Extension ISAPI ?
Créé le 04/04/2005[haut]
auteur : matazz
C'est simple dans la fonction en utilisant le CHttpServerContext :

unsigned longSize = 250;
LPTSTR ClientIP  = (LPTSTR) malloc(Size);

pCtxt->GetServerVariable("REMOTE_ADDR", ClientIP, &Size);

CStringIpClient = CString(ClientIP, Size);
free(ClientIP);
Les autres paramètres sont (CF MSDN):

Value Meaning
AUTH_TYPE : Contains the type of authentication used. If the string is empty, then no authentication is used.
CONTENT_LENGTH : The number of bytes which the script can expect to receive from the client.
CONTENT_TYPE : The content type of the information supplied in the body of a POST request.
GATEWAY_INTERFACE : The revision of the CGI specification to which this server complies. The current version is CGI/1.1.
PATH_INFO : Additional path information, as given by the client. This comprises the trailing part of the URL after the extension DLL (script) name but
before the query string (if any).
PATH_TRANSLATED : This is the value of PATH_INFO, but with any virtual path name expanded into a directory specification.
QUERY_STRING : The information which follows the ? in the URL which referenced this extension DLL.
REMOTE_ADDR : The IP address of the client.
REMOTE_HOST : The hostname of the client.
REMOTE_USER : This contains the username supplied by the client and authenticated by the server.
REQUEST_METHOD : The HTTP request method.
SCRIPT_NAME : The name of the extension DLL that is being executed.
SERVER_NAME : The server's hostname (or IP address) as it should appear in self-referencing URLs.
SERVER_PORT : The TCP/IP port on which the request was received.
SERVER_PROTOCOL : The name and version of the information retrieval protocol relating to this request. Normally HTTP/1.0.
SERVER_SOFTWARE : The name and version of the web server under which the ISA or server extension DLL program is running.
ALL_HTTP : All HTTP headers that were not already parsed into one of the above variables.
These variables are of the form HTTP_<header field name>.
HTTP_ACCEPT : Special case HTTP header. Values of the Accept: fields are concatenated, separated by ", ".
For example, if the following lines are part of the HTTP header:
accept: */*; q=0.1
accept: text/html
accept: image/jpeg

then the HTTP_ACCEPT variable will have a value of:

*/*; q=0.1, text/html, image/jpeg

Mise à jour :
Ce n'est pas signalé dans la MSDN mais on peut récupérer le type de navigateur du client en utilisant la même procédure avec la valeur HTTP_USER_AGENT


Comment redéfinir la fonction par défaut d'une DLL ISAPI ?
Créé le 04/04/2005[haut]
auteur : matazz
Attention ceci peut poser des problèmes car sur des requêtes HTTP en Post le client appelle la DLL dans un premier temps et n'envoie les paramètres que dans un second temps , ce qui à pour conséquence de déclencher la fonction par défaut (Constaté avec IE6, j'ai pas d'autre infos sur les autres Browsers).

La fonction par défaut est la fonction appelée quand on tape un requête du type sans paramètres :

http://www.monsite.com/Scripts/MyServerExtension.dll?
Sinon ça se passe dans la section BEGIN_PARSE_MAP, il suffit juste de rempacer le nom de la fonction qui va être appelée par défaut :

ON_PARSE_COMMAND(MaFonctionParDefaut, ClsMyServerExtension, ITS_EMPTY)
DEFAULT_PARSE_COMMAND(MaFonctionParDefaut, ClsMyServerExtension)

Comment Débugger une DLL ISAPI ?
Créé le 04/04/2005[haut]
auteur : matazz
Adapté à VC++ depuis : http://sjames.developpez.com/articles/ISAPIDebug/
Merci à Sylvain James pour les copies d'écran...
C'est assez compliqué et tordu mais c'est possible :
il vous faut le server IIS, et le service de composant COM et COM+
Première chose il ne faut pas avoir XP Home ou alors allez regarder ce lien : http://dotnet.developpez.com/IIS-sous-XP-Home/ car il n'y a pas le serveur IIS sous XP home édition.

Pour savoir si vous avez IIS installé faite bouton droit "gérer" puis dans "services et applications" vous devez avoir "services Internet (IIS)"
Première étape :
Installer IIS si nécessaire.
dans votre site Web par défaut, créer un répertoire virtuel (Appellons-le DLL) en cochant bien à la fin "Executer (par exemple, CGI ou application ISAPI)".
Ensuite clic droit "Propriétés" sur le dossier crée.

Dans "Protection d'application" choisir "élevée (Isolée)"

Deuxième étape : Il faut maintenant ouvrir la gestion des services COM et COM+ :
(je vous conseille de faire un raccourci)

sous XP : "C:\WINDOWS\system32\Com\comexp.msc"

Dans "Services de composants"->"Ordinateurs"->"Poste de travail"->"Applications COM+"
vous devez avoirs plusieurs process dont quelques uns commençant par IIS dont un notamment portant le nom de votre répertoire virtuel. Sur ce dernier Clic droit "Propriétés".

Dans l'onglet "Général" vous avez en bas "ID de L'application :"
suivi du CLSID de votre répertoire Virtuel sélectionnez-le et copiez-le . (Cela ce présente sous la forme : {BFC384AE-C057-4C64-8A04-3FC3EBEB00AD}).

Ensuite dans l'onglet "Identité" vérifiez que "Compte Système" soit bien coché (utilisateur actuellement connecté).

Vous pouvez maintenant fermer le gestionnaire des services COM+.

Tropisième et dernière étape :
Ouvrez votre projet dans visual studio.
Dans le Menu "Project"->"Settings" (ou ALt+F7)

Dans l'onglet "Debug" :

Dans l'Edit "Executable for debug session" mettre :
(sous XP, pour 2000 c'est C:\WINNT\...)
"C:\WINDOWS\system32\dllhost.exe"
Dans "Working directory" mettez le dossier physique sur lequel pointe votre dossier virtuel.
par exemple "C:\www\MonSite\Binary\DLL\"

Ensuite dans "Program Argument" mettez le CLSID que vous avez copié du gestionnaire de service COM+ comme suit :
"/ProcessID:{BFC384AE-C057-4C64-8A04-3FC3EBEB00AD}"

Enfin (C'est bientôt fini) dans l'onglet "Link" linkez votre exe dans le répertoire physique correspondant au répertiore virtuel :
"C:\www\MonSite\Binary\DLL\MyExtension.dll"
Fermer et faites "File"->"Save Workspace", ça serai bête de paumer les modifications.

Vous Pouvez maintenant lancer la version débug, mettez un point d'arrêt dans la fonction "Default", puis dans votre Browser tappez :
"http://localhost/DLL/MyExtension.dll?" et validez.

Remarque d'usage :

Si vous changez la protection d'application de votre répertoire virtuel, il faudra remettre dans le gestionnaire de services COM+ le compte Systeme.

Si vous voulez recompiler votre DLL suite à une modification, il vous faudra décharger la DLL de la mémoire afin de pouvoir réécrire sur la DLL sinon vous aurez un message du style "unable to link write error".
Pour décharger la DLL clic droit sur le répertoire virtuel "Propriétes" et il y a un bouton décharger.



Consultez les autres F.A.Q.


Valid XHTML 1.0 TransitionalValid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2004 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.