Exemple de VxD: MessageBox

Dans les tutorials précédent, vous avez appris le mécanisme de programmation des VxDs. Il est maintenant temps d'appliquer ce que vous avez appris. Dans ce tutorial, nous allons créer un simple VxD statique qui affichera une boîte de message (MessageBox) à chaque fois qu'une VM (une Machine Virtuelle) est créée ou détruite. Donc dès que vous lancerez un nouveau programme, une machine virtuelle sera créée pour qu'il tourne dessus et ainsi un MessageBox apparaîtera.
Téléchargez l'exemple ici.

Détection des événements de création et de terminaison d'une VM

Quand une VM est créée, le VMM (Manager de Machines Virtuelles) envoie le message de contrôle Create_VM à tous les VxDs. De la même façon, quand une VM est terminée (détruite) normalement, il envoie VM_Terminate et VM_Terminate2 à tous les VxDs. Notre travail est simple : notre programme va capturer les messages Create_VM et VM_Terminate2 dans sa procédure de contrôle de Device. Quand notre VxD reçoit ces deux messages de contrôle, il affiche une MessageBox à l'écran.
Quand notre VxD reçoit le message Create_VM ou VM_Terminate2, ebx contient le handle de la Machine Virtuelle (VM). Le handle de la VM peut être considéré comme un n°ID unique. Chaque VM a son unique ID (VM handle). Vous pouvez employer le handle de la Machine Virtuelle (VM) de la même façon que vous employez un n°ID pour un process, en le passant comme paramètre aux services qui en ont besoin.
En regardant de plus près, le handle de la VM est en réalité une adresse linéaire 32 bits du Le bloc de contrôle VM (VMCB).
Le Bloc de Contrôle VM est une structure qui contient plusieurs informations importantes sur la Machine Virtuelle (VM). Il est défini ainsi :

Affichage d'une MessageBox

Un VxD peut utiliser les services du Virtual Shell Device pour communiquer avec les utilisateurs. Dans cet exemple, nous allons utiliser un tel service. Nous allons utiliser SHELL_Message.
SHELL_Message est un service de registre. Vous passez vos paramètres grâce aux registres (on ne les pousse pas sur la pile). En retour, le flag CARRY est mis à 0 si l'appel est couronné de succès. Le flag CARRY est mis à 1 autrement.

Exemple

.386p
include vmm.inc
include shell.inc

DECLARE_VIRTUAL_DEVICE MESSAGE,1,0, MESSAGE_Control, UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER

Begin_control_dispatch MESSAGE
    Control_Dispatch Create_VM, OnVMCreate
    Control_Dispatch VM_Terminate2, OnVMClose
End_control_dispatch MESSAGE

VxD_PAGEABLE_DATA_SEG
    MsgTitle db "VxD MessageBox",0
    VMCreated db "A VM is created",0
    VMDestroyed db "A VM is destroyed",0
VxD_PAGEABLE_DATA_ENDS

VxD_PAGEABLE_CODE_SEG
BeginProc OnVMCreate
    mov ecx, OFFSET32 VMCreated
CommonCode:
    VMMCall Get_sys_vm_handle
    mov eax,MB_OK+MB_ICONEXCLAMATION
    mov edi, OFFSET32 MsgTitle
    xor esi,esi
    xor edx,edx
    VxDCall SHELL_Message
    ret
EndProc OnVMCreate

BeginProc OnVMClose
    mov ecx,OFFSET32 VMDestroyed
    jmp CommonCode
EndProc OnVMClose
VxD_PAGEABLE_CODE_ENDS

end

Analyse:

Begin_control_dispatch MESSAGE
    Control_Dispatch Create_VM, OnVMCreate
    Control_Dispatch VM_Terminate2, OnVMClose
End_control_dispatch MESSAGE
Le VxD traite les deux messages de contrôle, Create_VM et VM_Terminate2 . Lorsque le message Create_VM est reçu, on appelle la procédure OnVMCreate. Et quand il reçoit le message VM_Terminate2, on appelle la procedure OnVMClose.
VxD_PAGEABLE_DATA_SEG
    MsgTitle db "VxD MessageBox",0
    VMCreated db "A VM is created",0
    VMDestroyed db "A VM is destroyed",0
VxD_PAGEABLE_DATA_ENDS
Nous mettons les données dans le segment de données (pageable).
BeginProc OnVMCreate
    mov ecx, OFFSET32 VMCreated
CommonCode:
    VMMCall Get_sys_vm_handle
    mov eax,MB_OK+MB_ICONEXCLAMATION
    mov edi, OFFSET32 MsgTitle
    xor esi,esi
    xor edx,edx
   VxDCall SHELL_Message
    ret
EndProc OnVMCreate
La procédure OnVMCreate est créée en employant les macros BeginProc et EndProc. On met les paramètres pour du service SHELL_Message dans les registres. Puisque nous voulons afficher la MessageBox dans le système VM, nous ne pouvons pas utiliser la valeur de ebx (qui est le handle de la Machine Virtuelle VM qui est créée). Au lieu de ça, nous employons un service du Manager de Machines Virtuelles (VMM), Get_Sys_VM_handle, pour obtenir le handle du système VM (la Machine Virtuelle principale). Ce service renvoie le handle de la VM dans ebx. Nous plaçons respectivement les adresses du message et du titre dans ecx et edi. Nous ne souhaitons pas connaître la réponse de l'utilisateur, donc on met esi et edx à zéro. Quand tous les paramètres sont dans les registres appropriés, nous appelons SHELL_Message pour afficher la MessageBox.
BeginProc OnVMClose
    mov ecx,OFFSET32 VMDestroyed
    jmp CommonCode
EndProc OnVMClose
La procédure OnVMClose est une simplicité en soi. Puisque on emploie un code identique à celui de OnVMCreate, on initialise ecx avec l'adresse du message différent et on re-saute ensuite au code de OnVMCreate .

Module de définition des fichiers

VXD MESSAGE

SEGMENTS
    _LPTEXT      CLASS 'LCODE'    PRELOAD NONDISCARDABLE
    _LTEXT       CLASS 'LCODE'    PRELOAD NONDISCARDABLE
    _LDATA       CLASS 'LCODE'    PRELOAD NONDISCARDABLE
    _TEXT        CLASS 'LCODE'    PRELOAD NONDISCARDABLE
    _DATA        CLASS 'LCODE'    PRELOAD NONDISCARDABLE
    CONST        CLASS 'LCODE'    PRELOAD NONDISCARDABLE
    _TLS         CLASS 'LCODE'    PRELOAD NONDISCARDABLE
    _BSS         CLASS 'LCODE'    PRELOAD NONDISCARDABLE
    _LMGTABLE    CLASS 'MCODE'    PRELOAD NONDISCARDABLE IOPL
    _LMSGDATA    CLASS 'MCODE'    PRELOAD NONDISCARDABLE IOPL
    _IMSGTABLE   CLASS 'MCODE'    PRELOAD DISCARDABLE IOPL
    _IMSGDATA    CLASS 'MCODE'    PRELOAD DISCARDABLE IOPL
    _ITEXT       CLASS 'ICODE'    DISCARDABLE
    _IDATA       CLASS 'ICODE'    DISCARDABLE
    _PTEXT       CLASS 'PCODE'    NONDISCARDABLE
    _PMSGTABLE   CLASS 'MCODE'    NONDISCARDABLE IOPL
    _PMSGDATA    CLASS 'MCODE'    NONDISCARDABLE IOPL
    _PDATA       CLASS 'PDATA'    NONDISCARDABLE SHARED
    _STEXT       CLASS 'SCODE'    RESIDENT
    _SDATA       CLASS 'SCODE'    RESIDENT
    _DBOSTART    CLASS 'DBOCODE'  PRELOAD NONDISCARDABLE CONFORMING
    _DBOCODE     CLASS 'DBOCODE'  PRELOAD NONDISCARDABLE CONFORMING
    _DBODATA     CLASS 'DBOCODE'  PRELOAD NONDISCARDABLE CONFORMING
    _16ICODE     CLASS '16ICODE'  PRELOAD DISCARDABLE
    _RCODE       CLASS 'RCODE'

EXPORTS

    MESSAGE_DDB  @1

Processus d'assemblage

 ml -coff -c -Cx  -DMASM6 -DBLD_COFF -DIS_32 message.asm

 link -vxd -def:message.def message.obj

Installation du VxD

  1. Mettez le fichier 'message.vxd' dans le répertoire \system
  2. Ajoutez la ligne suivante à la fin de la section [386enh] qui se trouve dans le fichier system.ini
    1. device=message.vxd
  3. Redémarrez votre ordinateur

Test du VxD

Ouvrez une session DOS. Vous verrez la MessageBox, affichant le message, "une VM est créée (en anglais)". Quand vous refermez la fenêtre DOS, une autre MessageBox apparaît avec le message, "une VM est détruite".

[Iczelion's Win32 Assembly Homepage]


Traduit par Morgatte