Accueil
Qui suis-je ?
 
Mes livres
Les pompes rotodynamiques
Commander un livre
 
Mes programmes
Nopopup
Aide française
Télécharger
English help
Download
 
Optipump
English help
Download
 
SaveRes
Aide française
Télécharger
English help
Download
 
TTFName
Aide française
Télécharger
 
Mes articles
Composant ASP en C/C++
VxD W9x en ASM
 
Mes photos
Afrique australe
Autres photos
 
 visiteurs.
 pages vues.
 connecté(s).
Accueil-->VxD W9x en ASM - Chapitre 7

Application Time et fonctions du Shell

1 Introduction

Le temps d'application est communément appelé "appy time". Cela signifie simplement le temps où la VM système est assez stable pour permettre l'interaction entre VxD et applications en ring 3, particulièrement 16-bit.

Par exemple, pendant l’appy time, un VxD peut charger et appeler des fonctions de DLL 16-bit.

L’appy time n'est pas disponible sous Windows 3.1x. Sous Windows 3.1x, un VxD peut obtenir l'adresse de n'importe quelle fonction dans une DLL 16-bit et simuler un far call à cette adresse. Cependant, cela interrompra n'importe quelle tâche dans le ring-3 en raison de la réentrance du VMM. Donc les seules API que VxD peut appeler sont ceux qui celles qui ne font pas appel aux interruptions comme PostMessage.

Sous Windows 9x, un VxD peut appeler pratiquement n'importe quelle fonction dans n'importe quel DLL 16-bit avec l'aide de l’ appy time.

Très simplement, si votre VxD est averti de l’appy time, il peut charger une DLL 16-bit et y appeler des fonctions. Ainsi comment un VxD est il averti de l’appy time ?

Il doit enregistrer un événement appy time avec le Shell VxD. Sous réserve que la VM système soit dans un état stable, le Shell VxD appellera la fonction de rappel que le VxD a spécifié quand il a enregistré un événement appy time. Le Shell VxD appellera votre fonction de rappel une seule fois pour chaque enregistrement d’événement d’appy time.

C’est comme la recherche d'un job. Vous allez à une agence de recrutement, et lui communiquez votre nom et votre numéro de téléphone et retournez à la maison. Quand un travail est vaquant, l'agence vous téléphone. Vous en prenez connaissance et elle ne vous rappelle plus à ce sujet.

Cela peut prendre un certain temps avant qu'un événement appy time survienne. Les événements appy time ne sont pas disponibles dans certaines circonstances : Pendant le démarrage ou l'arrêt du système et quand la VM système est dans une section critique ou attend un sémaphore

2 Gestion d'un événement appy time

Vous pouvez enregistrer événement appy time en appelant _SHELL_CallAtAppyTime définie comme suit :

VxDCall _SHELL_CallAtAppyTime, <<OFFSET32 pfnCallback>, dwRefData, dwFlags, dwTimeout>

pfnCallBack est l'adresse linéaire de la fonction de rappel qui doit être appelée par le Shell VxD quand un événement appy time survient. La fonction recevra deux paramètres, dwRefData et dwFlags qui sont exactement identiques aux deux paramètres que vous avez passé à _SHELL_CallAtAppyTime. Notez que le Shell VxD appellera votre fonction de rappel avec la convention d'appel C. Vous devez définir votre fonction de rappel de service comme détaillé ci après. Ce service est asynchrone, ce qui signifie qu'il retourne immédiatement après l'enregistrement de votre callback de l'événement appy time.

BeginProc OnAppyTime, CCALL, PUBLIC
ArgVar dwRefData, DWORD ;         déclaration nom et type arguments
ArgVar dwFlags, DWORD
EnterProc
<Votre code ici>
LeaveProc
Return
EndProc OnAppyTime

  • dwRefData
    La référence aux données que vous voulez que le Shell VxD passe à votre fonction de rappel. Cela peut être tout ce que vous voulez.
  • dwFlags
    Flags d’événement. Une des valeurs suivantes:
    - CAAFL_RING0 évènement Ring-0.
    - CAAFL_TIMEOUT Dépassement de la durée spécifiée par dwTimeout.
    Simplement si vous voulez attendre l'événement de temps appy pour une certaine période seulement, employez le drapeau CAAFL_TIMEOUT. Si vous voulez attendre indéfiniment l'événement de temps appy, employez le NULL. Je ne sais pas ce que CAAFL_RING0 fait en réalité.
  • wTimeout
    La période de temps ou le VxD doit attendre l'événement appy time. Je n'ai pas trouvé de renseignements concernant l'unité de temps employée avec cet argument. 
  • En cas de succès, le handle de l’application gérant l’appy time est retourné dans eax.

    En cas d’échec, eax contient 0.

    3 Compléments

    Vous pouvez annuler l'enregistrement de temps appy en appelant _SHELL_CancelAppyTimeEvent qui prend un seul paramètre, le handle d'événement de temps appy fourni par _SHELL_CallAtAppyTime.

    Par sécurité, avant l'appel _SHELL_CallAtAppyTime, contrôlez le système pour vérifier si l'événement appy time peut être disponible.

    Par exemple, que ce passe t'il si vous enregistrez un événement appy time alors que le système s'arrête ?

    La fonction de rappel de votre VxD ne sera jamais appelée! Vous pouvez savoir si un événement de temps appy peut être disponible en appelant _SHELL_QueryAppyTimeAvailable.

    Ce service ne prend aucun paramètre. Il retourne 0 dans eax si l’appy time ne peut être disponible, comme par exemple si le système se ferme ou le serveur de messages a obtenu des fautes de protection générale. Ce service ne vous averti pas d’un appy time: il vous dit seulement qu'il peut y avoir des événements appy time.

    Bref, si vous voulez jouer la sécurité, appelez _SHELL_QueryAppyTimeAvailable d'abord et s'il rend une valeur non nulle dans eax, vous pouvez appeler _SHELL_CallAtAppyTime.

    4 Services Appy Time du Shell

    4.1 Généralités

    Quand l’appy time est atteint, il y a plusieurs services du Shell que vous pouvez appeler :

  • _SHELL_CallDll
  • _SHELL_FreeLibrary
  • _SHELL_GetProcAddress
  • _SHELL_LoadLibrary
  • _SHELL_LocalAllocEx
  • _SHELL_LocalFree
  • Ces six services sont fournis pour que les VxD puissent appeler des fonctions 16-bit de DLL ou d' EXE 16-bit, comme WinHelp. Cependant, puisque vivons dans un monde 32-bit (et 64-bit bientôt !), Je n'entrerai pas dans leurs détails. Si vous êtes intéressés, consultez la documentation du DDK.

    D’autres appels du Shell sont plus utiles : _SHELL_ShellExecute et _SHELL_BroadcastSystemMessage. Avec _SHELL_BroadcastSystemMessage, vous pouvez envoyer un message à toutes les fenêtres de plus haut niveau et à tous les VxD via un seul appel Si l’appy time est disponible, vous pouvez envoyer des messages à toutes les fenêtres et VxD. Si l’appy time n'est pas disponible, vous pouvez n’envoyer des messages qu’aux VxD.

    _SHELL_ShellExecute est l'homologue en ring-0 de la fonction ShellExecute dans le ring-3. En réalité cette fonction appelle ShellExecute en ring-3 pour faire le travail. Avec ce service de shell, vous pouvez exécuter, ouvrir, imprimer n'importe quel fichier.

    _SHELL_ShellExecute a la définition suivante :

    VxDCall _SHELL_ShellExecute, <OFFSET32 ShexPacket>

    Il n'y a qu'un seul paramètre, l'adresse linéaire de structure SHEXPACKET. La valeur de retour de ShellExecute est dans eax.

    4.2 La structure de SHEXPACKET

  • shex_dwTotalSize
    La taille en octets de la structure SHEXPACKET plus le paramètre facultatif, rgchBaggage, qui suit immédiatement cette structure. Je décrirai rgchBaggage bientôt.
  • shex_dwSize
    La taille en octets de la structure SHEXPACKET, sans compter rgchBaggage. Combiné avec shex_dwTotalSize ci-dessus, le Shell peut calculer la taille de rgchBaggage qui est de longueur arbitraire.
  • shex_ibOp
    L'opération que vous voulez exécuter. Si vous spécifiez 0, cela signifie que vous voulez ouvrir un fichier. Si le fichier est exécutable, il est exécuté. Si vous voulez exécuter une autre opération, vous devez spécifier le nom de l'opération quelque part dans rgchBaggage et ce champ doit contenir le décalage en octets du début de cette structure de SHEXPACKET au premier caractère de la chaîne ASCIIZ qui spécifie le nom de l'opération que vous voulez exécuter. La taille de SHEXPACKET est de 32 octets. Si la chaîne d'opération suit immédiatement la structure de SHEXPACKET, la valeur dans shex_ibOp DOIT ÊTRE 32. Quant à la liste des opérations vous pouvez exécuter, examinez ShellExecute. Il y a trois opérations définies, "open", "print" et "explore".
  • shex_ibFile
    La distance relative du début de la structure à la chaîne ASCIIZ qui est le nom du fichier vous voulez envoyer à ShellExecute, comme pour shex_ibOp.
  • shex_ibParams
    Les paramètres facultatifs que vous voulez passer au fichier indiqué dans shex_ibFile. Si le fichier est un document ou si vous ne voulez pas passer de paramètres, employez 0. Si vous voulez passer des paramètres au fichier, mettez la chaîne de paramètres quelque part après cette structure et indiquez son offset avec le début de la structure dans ce champ, comme pour shex_ibOp et shex_ibFile.
  • shex_ibDir
    Le répertoire de travail. Spécifiez 0 si vous voulez employer le répertoire de Windows. Dans le cas contraire spécifiez la chaîne représentant le répertoire et mettez l’offset entre le début de la chaîne et le début de la structure dans ce champ.
  • shex_dwReserved
    Comme le nom l'indique, il est réservé.
  • shex_nCmdShow
    Comment afficher la fenêtre de l'application. C'est une de la valeur que vous passez normalement à ShowWindow du type SW_XXX. Cherchez ces valeurs dans windows.inc.
  • 4.3 Compléments

    Tous les membres sont de type DWORD. Maintenant voici le détail de rgchBaggage que je vous ai promis. C’ est un peu difficile à expliquer. rgchBaggage est un membre de la structure SHEXPACKET mais il ne peut pas être inclus dans la définition de structure parce que sa taille est arbitraire. Vérifiez shell.inc, vous verrez que rgchBaggage n'est pas défini dans SHEXPACKET bien que la documentation du DDK affirme le contraire.

    Qu'est ce rgchBaggage ? C'est simplement un tableau de chaînes de caractères ASCIIZ qui suit la structure de SHEXPACKET. Dans ce tableau, vous pouvez mettre le nom de l'opération que vous voulez exécuter, le nom du fichier, les paramètres que vous voulez passer et une liste de répertoires. Le Shell VxD obtient l'adresse de la chaîne dans rgchBaggage en ajoutant la distance relative entre la structure de SHEXPACKET et le premier octet de la chaîne à l'adresse linéaire de SHEXPACKET. Par exemple, si la structure de SHEXPACKET commence à 60000h et que la chaîne suit immédiatement la structure, la distance entre la structure et la chaîne correspond à la taille de la structure elle-même, soit 32 (20h). Donc le Shell VxD sait que la chaîne est à l'adresse 60020h.

    5 Exemple

    5.1 Généralités

    Ce sera un exemple très simple, juste pour vous montrer comment enregistrer un événement appy time et employer _SHELL_ShellExecute. Le VxD dynamique est chargé par une application simple win32.

    Quand l'utilisateur presse "Calculer", l'application win32 appelle DeviceIoControl pour demander au VxD d'enregistrer un événement de temps appy et lance calc.exe dans le répertoire de Windows.

    5.2 Code

    ;---------------------------------------------------------------
    ;                      Code Source VxD
    ;---------------------------------------------------------------
    .386p
    include \masm\include\vmm.inc
    include \masm\include\vwin32.inc
    include \masm\include\shell.inc

    VxDName ;  TEXTEQU <VXDEXEC>
    ;  ControlName TEXTEQU <VXDEXEC_Control>
    ;  VxDMajorVersion TEXTEQU <1>
    ;  VxDMinorVersion TEXTEQU <0> VxD_STATIC_DATA_SEG
    VxD_STATIC_DATA_ENDS
    VXD_LOCKED_CODE_SEG
    ;---------------------------------------------
    ;Rappel : Le nom du VxD DOIT être en majuscules
    ;---------------------------------------------
    DECLARE_VIRTUAL_DEVICE %VxDName,%VxDMajorVersion,%VxDMinorVersion, %ControlName, UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER

    Begin_control_dispatch %VxDName
            Control_Dispatch W32_DEVICEIOCONTROL, OnDeviceIoControl
    End_control_dispatch %VxDName

    BeginProc OnDeviceIoControl
     assume esi:ptr DIOCParams
     .if [esi].dwIoControlCode==1
          VxDCall _SHELL_CallAtAppyTime,<<OFFSET32 OnAppyTime>,0,0,0>
     .endif
     xor eax, eax
     ret
    EndProc OnDeviceIoControl
    VXD_LOCKED_CODE_ENDS

    VXD_PAGEABLE_CODE_SEG
    BeginProc OnAppyTime, CCALL
     ArgVar RefData, DWORD 
     ArgVar TheFlag, DWORD
     EnterProc
     mov File.shex_dwTotalSize, sizeof SHEXPACKET
     add File.shex_dwTotalSize, sizeof EXEName
     mov File.shex_dwSize, sizeof SHEXPACKET
     mov File.shex_ibOp,0
     mov File.shex_ibFile, sizeof SHEXPACKET
     mov File.shex_ibParams,0
     mov File.shex_ibDir,0
     mov File.shex_dwReserved,0
     mov File.shex_nCmdShow,1
     VxDCall _SHELL_ShellExecute, <OFFSET32 File>
     LeaveProc
     Return
    EndProc OnAppyTime
    VXD_PAGEABLE_CODE_ENDS

    VXD_PAGEABLE_DATA_SEG
     File SHEXPACKET <>
     EXEName db "calc.exe",0
    VXD_PAGEABLE_DATA_ENDS

    end

    5.3 Analyse

    Le VxD attend les messages du service N°1 de DeviceIoControl, service n°1. Quand il reçoit un tel message, il enregistre un événement appy time.

    VxDCall _SHELL_CallAtAppyTime,<<OFFSET32 OnAppyTime>,0,0,0>

    Il passe l'adresse linéaire de la fonction OnAppyTime à _SHELL_CallAtAppyTime pour que le Shell VxD puisse l'appeler quand un événement appy time survient. Nous n'employons pas de référence de données et ne nous occuperons pas des temps morts donc tous les trois paramètres suivants sont à 0.

    Quand un événement appy time survient, le Shell VxD appelle la fonction OnAppyTime.

    BeginProc OnAppyTime, CCALL

    Nous déclarons une fonction avec BeginProc. Puisque l'appel OnAppyTime par le Shell VxD est de type C, nous devons spécifier l'attribut de CCALL.

    ArgVar RefData, DWORD
    ArgVar TheFlag, DWORD
    EnterProc
    ...
    LeaveProc
    Return

    Puisque le Shell VxD appelle OnAppyTime avec deux paramètres, nous devons préparer la pile en conséquence. La macro ArgVar est conçue pour adapter la pile à chacun des arguments passés à la fonction. Sa syntaxe est la suivante :

    ArgVar  varname, size, used

    varname est le nom du paramètre. Vous pouvez employer n'importe quel nom de votre choix. La taille est, bien sûr, la taille du paramètre en octets. Vous pouvez employer BYTE, WORD, DWORD ou 1,2,4. USED est d'habitude omis.

    Immédiatement après ArgVar, nous devons employer les macros EnterProc et LeaveProc pour marquer le commencement et la fin des instructions dans la procédure de manière à ce que les variables locales et les paramètres puissent être accessibles. Utilisez Return pour retourner à l'appelant.

     mov File.shex_dwTotalSize, sizeof SHEXPACKET
     add File.shex_dwTotalSize, sizeof EXEName
     mov File.shex_dwSize, sizeof SHEXPACKET
     mov File.shex_ibOp, 0
     mov File.shex_ibFile, sizeof SHEXPACKET
     mov File.shex_ibParams, 0
     mov File.shex_ibDir, 0
     mov File.shex_dwReserved, 0
     mov File.shex_nCmdShow, 1
     VxDCall _SHELL_ShellExecute, <OFFSET32 File>

    Les instructions à l'intérieur de la procédure sont simples : initialisez la structure SHEXPACKET et appelez le service _SHELL_ShellExecute. Notez que shex_dwTotalSize contient la taille de la structure de SHEXPACKET elle-même et de la taille de la chaîne qui la suit. C'est le cas simple. Si la chaîne ne suit pas immédiatement la structure, vous devez calculer la distance entre le premier octet de la structure et le dernier octet de la chaîne par vous-même. Shex_ibFile contient la taille de la structure seule parce que le nom du programme suit immédiatement la structure. Shex_ibDir est à 0 signifiant que le répertoire de Windows sera le répertoire de travail. Notez que cela ne signifie pas que le programme doit être dans ce répertoire. Le programme peut être n'importe où, tant que Windows puisse le trouver. Shex_nCmdShow est égal à 1 qui est la valeur SW_SHOWNORMAL.

    File SHEXPACKET <>
    EXEName db "calc.exe",0

    Nous définissons une structure SHEXPACKET suivie immédiatement par le nom du programme que nous voulons exécuter.

    Page:  1  2  3  4  5  6  8  9 

    Précédent       Suivant

    Copyright © Jean-Pierre Fayeulle