cs_EBArtSoft
Messages postés4525Date d'inscriptiondimanche 29 septembre 2002StatutModérateurDernière intervention22 avril 20199 24 juil. 2007 à 19:00
Cool je vais voir la maj chez toi
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 24 juil. 2007 à 11:32
j'ai ajouté un test (en mode IDE) qui s'assure que le code tourne (EbMode) et si on est en BreakPoint, on appelle la proc standard.
(ce code de test n'est pas greffé en mode compile)
au final, on peut debugger tranquille, et même presser le bouton STOP, sans que VB en crashes...
bref, ce que j'avais suggeré dans mon tout premier commentaire sur ta source.
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 24 juil. 2007 à 09:50
j'ai codé ce forward d'appel en C, puis j'ai modifié un tout petit peu le listing asm que m'a filé le compilateur de VS2005...
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 23 juil. 2007 à 22:32
ah... ouais, remarques, c'est assez logique...
enfin, j'étais content d'avoir (enfin) réussi a ce que ca plante pas :p => voir le coté positif ^^
ba, j'vais trouver autre chose...(où utiliser ton code :p)
là, j'appelais une fonction de mes objets (ISubClasser), donc j'ai pas a me soucier de l'emplacement de la procedure dans le code...
cs_EBArtSoft
Messages postés4525Date d'inscriptiondimanche 29 septembre 2002StatutModérateurDernière intervention22 avril 20199 23 juil. 2007 à 19:37
La pile c'est le plus long ! Car c'est un acces memoire + une incrementation/decrementation de registre. Donc moins il y en as mieu on ce porte.
Cela dit comme disait le grand maitre cinquante : "il ne faut presumer de rien"
@+
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 23 juil. 2007 à 15:14
A voir avec les spécialistes de l'Asm... mais je pense que c'est plus rapide ainsi. Je ne passe que par la pile et les registres.
j'ai mis le nez dans la windowproc, (et après moultes crash, quelques heures passées sous IDA) :
MovB Ofs, &H55 ' PUSH EBP on sauvegarde EBP
MovB Ofs, &H5B ' POP EBX on fais avancer la pile
MovB Ofs, &H5D ' POP EBP on récupère l'adresse de retour
MovB Ofs, &H5A ' POP EDX on dépile ensuite les parametres... lParam
MovB Ofs, &H59 ' POP ECX wParam
MovB Ofs, &H58 ' POP EAX uMsg
MovB Ofs, &H5B ' POP EBX hWnd
MovB Ofs, &H55 ' PUSH EBP On replace l'adresse de retour
MovB Ofs, &H52 ' PUSH EDX Allocation sur la pile de la valeur de retour
MovB Ofs, &H54 ' PUSH ESP Le parametre RetValue de la méthode COM appelée sera placé sur la pile
MovB Ofs, &H8B ' MOV EBP, [ESP-0Ch] On recupère la valeur de EBP, placée temporairement dans la pile
MovB Ofs, &H6C '
MovB Ofs, &H24 '
MovB Ofs, &HF4 '
MovB Ofs, &H53 ' PUSH EBX On empile les paramètres... lParam
MovB Ofs, &H50 ' PUSH EAX wParam
MovB Ofs, &H51 ' PUSH ECX uMsg
MovB Ofs, &HBB ' MOV EBX, 22222222h Pointeur de la fonction à appeler
MovL Ofs, Ptr '
MovB Ofs, &H52 ' PUSH EDX hWnd
MovB Ofs, &H68 ' PUSH 55555555h ObjPtr de l'objet concerné
MovL Ofs, ObjPtr(Me) '
MovB Ofs, &HFF ' CALL EBX On effectue l'appel proprement dit
MovB Ofs, &HD3 '
MovB Ofs, &H58 ' POP EAX Et on récupère la valeur de retour
MovB Ofs, &HC3 ' RET Pas de parametre ici, ils ont d'ores et deja été dépilés
soient 32 octets de bytecode.
cs_EBArtSoft
Messages postés4525Date d'inscriptiondimanche 29 septembre 2002StatutModérateurDernière intervention22 avril 20199 7 sept. 2006 à 13:10
Oui lol mais je voulais pas plus compliqué le truc :p
mais en effet il faut empiler l'adresse de l'objet apres tout les autres prametres. Comme c'est "après" ça ne pose pas trop de probleme un pop, deux push le tour est joué.
@+
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 7 sept. 2006 à 12:34
Pour les objets COM, c'est même :
Function X(ByRef Me As IUnkown, ByVal P1 As Long, ByRef RetVal As Long) As Long
me semble-t'il ^^
cs_EBArtSoft
Messages postés4525Date d'inscriptiondimanche 29 septembre 2002StatutModérateurDernière intervention22 avril 20199 7 sept. 2006 à 12:29
En faites c'est "presque" ça Renfield :p
Les modules de classe et autres objet VB (form, control etc...) ne peuvent pas renvoyer de valeur telle qu'on les concois dans du code C ou Assembleur c'est a dire si l'on ecris Function X() As Long dans un module standard c'est EAX qui aura la valeur de retour mais pas dans un module de classe ou la c'est un HRESULT qui sera renvoyé comme cela est exposé dans la documentation COM. Hors vb permet tout de même le renvoi de valeur ?!? C'est ce principe que j'ai mi un peu de temps a comprendre en faite lorsque vous ecrivez ceci :
Function X(byval P1 as long) As Long
Cela devient en machine :
Function X(ByVal P1 As Long, ByRef RetVal As Long) As Long
La valeur retourné par la fonction est un code d'erreur COM
La vrais valeur de retour est dans RetVal qui prend le type de la fonction de depart en byref biensur ce qui nous oblige a créer une variable temporaire lors d'un appel. Donc le code transforme simplement l'appel a WindowProc classique par un appel a une WindowProc de type COM et le tour est joué.
On ne modifie en rien les objets crée par VB on crée juste une mini fonction ASM que windows va appelé a chaque WM_MESSAGE et qui va en quelques sorte traduire l'appel ! C'est tres simple et en même temps complexe. Le plus dure est de recuperer le bon pointeur de fonction car AddressOf n'est pas compatible avec les module de classe.
Pour cela vous trouverez dans les exemples un code encore tres simple qui permet de retrouver le bon pointeur en fonction du type d'objet hôte. Le tout est bien entendu modulable a souhait puisque l'on ce debarrasse une fois pour toute de ce maudit module trop trop trop rigide a mon gout.
Pour ce qui est de la restriction syntaxique Ren a encore raison si on place une autre routine public devant la windowproc elle perdra sa premiere place dans la VTable (ou table d'adressage) ce qui a pour consequence de tout fausser. On peux le faire a condition de changé l'index dans le code d'initialisation. Pour comprendre comparez les code Form,Class,Usercontrol
Voila pour les explications
B@nne prog
bouv
Messages postés1411Date d'inscriptionmercredi 6 août 2003StatutMembreDernière intervention 3 mars 20191 7 sept. 2006 à 12:04
On en apprend tout les jours.
Merci.
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 7 sept. 2006 à 11:57
Bouv, c'est parce que sinon, elle ne sera pas retrouvée.
les objets COm on un tableau (VTable) qui contient l'addresse des fonctions en mémoire
si on ajoute une fonction avant, par exemple, WindowProc sera dans la case suivante de la VTable, et tout sera faussé.
EB, ici, remplace 'simplement' le pointeur de fonction de la VTable, pour pointer vers un tableau contenant du Bytecode ASM. Ce faisant, c'est ce code qui est executé en lieu et place de la fonction WindowProc que tu vois.
en passant, ShareVB, clair, très bon bouquin ^^
ShareVB
Messages postés2676Date d'inscriptionvendredi 28 juin 2002StatutMembreDernière intervention13 janvier 201626 7 sept. 2006 à 11:49
salut à tous,
génial et chapeau bas... parce que même l'auteur de Avanced VB6 For Everyday Programs ne l'expose pas dans son bouquin...
bouv
Messages postés1411Date d'inscriptionmercredi 6 août 2003StatutMembreDernière intervention 3 mars 20191 7 sept. 2006 à 11:41
Bon, j'ai pense avoir pigé l'essentiel (dans le principe).
J'ai juste une question : pourquoi la fonction 'WindowProc' ne peut-elle pas être déplacée ?
cs_moustachu
Messages postés1079Date d'inscriptionjeudi 14 novembre 2002StatutMembreDernière intervention 1 janvier 2012 7 sept. 2006 à 08:40
Ca démèresachire....
Très bien organisé. Pour l'optimiser, je ne sais pas, je vais d'abord essayé de le comprendre ;o)
++
Moustachu
Renfield
Messages postés17287Date d'inscriptionmercredi 2 janvier 2002StatutModérateurDernière intervention27 septembre 202174 7 sept. 2006 à 06:28
Sympa, comme toujours ^^
bel exemple d'injection ASM, une fois de plus ^^
coté IDE, j'ai pu constater dans mes propres codes que l'API EbMode (vba6.dll) permettait de bien stabiliser la chose...
Elle renvoie 1 si tu es en mode execution, et indique, dans le cas contraire un BreakPoint.
Si tel est le cas (BP), tu pourrais alors ne pas invoquer (test dans le code ASM) la WindowProc de l'utilisateur, qu'en pennses-tu ?
24 juil. 2007 à 19:00
24 juil. 2007 à 11:32
(ce code de test n'est pas greffé en mode compile)
au final, on peut debugger tranquille, et même presser le bouton STOP, sans que VB en crashes...
bref, ce que j'avais suggeré dans mon tout premier commentaire sur ta source.
24 juil. 2007 à 09:50
ça me donne donc 41 octets :
MovB Ofs, &H51 'push ecx
MovL Ofs, &H14244C8B 'mov ecx, DWORD PTR _lParam$[esp] (_lParam$=20)
MovL Ofs, &H1024548B 'mov edx, DWORD PTR _wParam$[esp] (_wParam$=16)
MovB Ofs, &H8D 'lea eax, DWORD PTR _RetValue$[esp+4] (_RetValue$=-4)
MovB Ofs, &H4
MovB Ofs, &H24
MovB Ofs, &H50 'push eax
MovL Ofs, &H1024448B 'mov eax, DWORD PTR _uMsg$[esp+4] (_uMsg$=12)
MovB Ofs, &H51 'push ecx
MovL Ofs, &H10244C8B 'mov ecx, DWORD PTR _hWnd$[esp+8] (_hWnd$=8)
MovB Ofs, &H52 'push edx
MovB Ofs, &H50 'push eax
MovB Ofs, &H51 'push ecx
MovB Ofs, &H68 'push 0x55555555
MovL Ofs, ObjPtr(x)
MovB Ofs, &HBA 'mov edx, 0x22222222
MovL Ofs, Ptr
MovB Ofs, &HFF 'call edx
MovB Ofs, &HD2
MovB Ofs, &H58 'pop eax
MovB Ofs, &HC2 'ret 16 ; 00000010H
MovB Ofs, &H10
MovB Ofs, &H0
23 juil. 2007 à 22:32
enfin, j'étais content d'avoir (enfin) réussi a ce que ca plante pas :p => voir le coté positif ^^
ba, j'vais trouver autre chose...(où utiliser ton code :p)
là, j'appelais une fonction de mes objets (ISubClasser), donc j'ai pas a me soucier de l'emplacement de la procedure dans le code...
23 juil. 2007 à 19:37
Cela dit comme disait le grand maitre cinquante : "il ne faut presumer de rien"
@+
23 juil. 2007 à 15:14
j'ai mis le nez dans la windowproc, (et après moultes crash, quelques heures passées sous IDA) :
MovB Ofs, &H55 ' PUSH EBP on sauvegarde EBP
MovB Ofs, &H5B ' POP EBX on fais avancer la pile
MovB Ofs, &H5D ' POP EBP on récupère l'adresse de retour
MovB Ofs, &H5A ' POP EDX on dépile ensuite les parametres... lParam
MovB Ofs, &H59 ' POP ECX wParam
MovB Ofs, &H58 ' POP EAX uMsg
MovB Ofs, &H5B ' POP EBX hWnd
MovB Ofs, &H55 ' PUSH EBP On replace l'adresse de retour
MovB Ofs, &H52 ' PUSH EDX Allocation sur la pile de la valeur de retour
MovB Ofs, &H54 ' PUSH ESP Le parametre RetValue de la méthode COM appelée sera placé sur la pile
MovB Ofs, &H8B ' MOV EBP, [ESP-0Ch] On recupère la valeur de EBP, placée temporairement dans la pile
MovB Ofs, &H6C '
MovB Ofs, &H24 '
MovB Ofs, &HF4 '
MovB Ofs, &H53 ' PUSH EBX On empile les paramètres... lParam
MovB Ofs, &H50 ' PUSH EAX wParam
MovB Ofs, &H51 ' PUSH ECX uMsg
MovB Ofs, &HBB ' MOV EBX, 22222222h Pointeur de la fonction à appeler
MovL Ofs, Ptr '
MovB Ofs, &H52 ' PUSH EDX hWnd
MovB Ofs, &H68 ' PUSH 55555555h ObjPtr de l'objet concerné
MovL Ofs, ObjPtr(Me) '
MovB Ofs, &HFF ' CALL EBX On effectue l'appel proprement dit
MovB Ofs, &HD3 '
MovB Ofs, &H58 ' POP EAX Et on récupère la valeur de retour
MovB Ofs, &HC3 ' RET Pas de parametre ici, ils ont d'ores et deja été dépilés
soient 32 octets de bytecode.
7 sept. 2006 à 13:10
mais en effet il faut empiler l'adresse de l'objet apres tout les autres prametres. Comme c'est "après" ça ne pose pas trop de probleme un pop, deux push le tour est joué.
@+
7 sept. 2006 à 12:34
Function X(ByRef Me As IUnkown, ByVal P1 As Long, ByRef RetVal As Long) As Long
me semble-t'il ^^
7 sept. 2006 à 12:29
Les modules de classe et autres objet VB (form, control etc...) ne peuvent pas renvoyer de valeur telle qu'on les concois dans du code C ou Assembleur c'est a dire si l'on ecris Function X() As Long dans un module standard c'est EAX qui aura la valeur de retour mais pas dans un module de classe ou la c'est un HRESULT qui sera renvoyé comme cela est exposé dans la documentation COM. Hors vb permet tout de même le renvoi de valeur ?!? C'est ce principe que j'ai mi un peu de temps a comprendre en faite lorsque vous ecrivez ceci :
Function X(byval P1 as long) As Long
Cela devient en machine :
Function X(ByVal P1 As Long, ByRef RetVal As Long) As Long
La valeur retourné par la fonction est un code d'erreur COM
La vrais valeur de retour est dans RetVal qui prend le type de la fonction de depart en byref biensur ce qui nous oblige a créer une variable temporaire lors d'un appel. Donc le code transforme simplement l'appel a WindowProc classique par un appel a une WindowProc de type COM et le tour est joué.
On ne modifie en rien les objets crée par VB on crée juste une mini fonction ASM que windows va appelé a chaque WM_MESSAGE et qui va en quelques sorte traduire l'appel ! C'est tres simple et en même temps complexe. Le plus dure est de recuperer le bon pointeur de fonction car AddressOf n'est pas compatible avec les module de classe.
Pour cela vous trouverez dans les exemples un code encore tres simple qui permet de retrouver le bon pointeur en fonction du type d'objet hôte. Le tout est bien entendu modulable a souhait puisque l'on ce debarrasse une fois pour toute de ce maudit module trop trop trop rigide a mon gout.
Pour ce qui est de la restriction syntaxique Ren a encore raison si on place une autre routine public devant la windowproc elle perdra sa premiere place dans la VTable (ou table d'adressage) ce qui a pour consequence de tout fausser. On peux le faire a condition de changé l'index dans le code d'initialisation. Pour comprendre comparez les code Form,Class,Usercontrol
Voila pour les explications
B@nne prog
7 sept. 2006 à 12:04
Merci.
7 sept. 2006 à 11:57
les objets COm on un tableau (VTable) qui contient l'addresse des fonctions en mémoire
si on ajoute une fonction avant, par exemple, WindowProc sera dans la case suivante de la VTable, et tout sera faussé.
EB, ici, remplace 'simplement' le pointeur de fonction de la VTable, pour pointer vers un tableau contenant du Bytecode ASM. Ce faisant, c'est ce code qui est executé en lieu et place de la fonction WindowProc que tu vois.
en passant, ShareVB, clair, très bon bouquin ^^
7 sept. 2006 à 11:49
génial et chapeau bas... parce que même l'auteur de Avanced VB6 For Everyday Programs ne l'expose pas dans son bouquin...
Pour ceux qui voudrait en savoir plus sur le fonctionnement interne de VB6 et comprendre un peu plus ce merveilleux code :
http://www.vbfrance.com/tutoriaux/OBJETS-COM-VB_162.aspx
http://www.vbfrance.com/tutoriaux/OBJETS-LEGERS-CONCEPT-POUR-OPTIMISER-CLASSES-VB_173.aspx
http://www.vbfrance.com/tutoriaux/APPELER-POINTEURS-FONCTIONS-DEPUIS-VB_176.aspx
http://www.vbfrance.com/tutoriaux/METTRE-ASSEMBLEUR-DANS-VB-FONCTIONNE-DANS-IDE-COMPILE_186.aspx
et accessoirement :
http://www.vbfrance.com/tutoriaux/BIBLIOTHEQUES-TYPES-TYPELIB-TLB-LANGAGE-ODL_165.aspx
http://www.vbfrance.com/tutoriaux/FOURNIR-FONCTIONS-CALLBACKS-AUTRES-STDCALL_187.aspx
ou pour plus de lisibilité, les articles sont aussi là :
http://www.sharevb.net/-VB-.html
et enfin, le bouquin "Advanced Visual Basic 6"
désolé pour la pub...
ShareVB
7 sept. 2006 à 11:41
J'ai juste une question : pourquoi la fonction 'WindowProc' ne peut-elle pas être déplacée ?
7 sept. 2006 à 08:40
Très bien organisé. Pour l'optimiser, je ne sais pas, je vais d'abord essayé de le comprendre ;o)
++
Moustachu
7 sept. 2006 à 06:28
bel exemple d'injection ASM, une fois de plus ^^
coté IDE, j'ai pu constater dans mes propres codes que l'API EbMode (vba6.dll) permettait de bien stabiliser la chose...
Elle renvoie 1 si tu es en mode execution, et indique, dans le cas contraire un BreakPoint.
Si tel est le cas (BP), tu pourrais alors ne pas invoquer (test dans le code ASM) la WindowProc de l'utilisateur, qu'en pennses-tu ?