Zoom Icon

Usare le DirectDraw

From UIC

How to use DirectDraw in Win32ASM

Contents


Infos
Author: X-Calibre
Email:
Website:
Date: 01/01/2001 (dd/mm/yyyy)
Level: No brain needed
Language: English Image:Flag_English.gif
Comments:



Link e Riferimenti

Sources


Introduzione

Well, there has been quite a large demand for this essay, so I finally started writing it. This essay will show you how to use C++ objects and COM interface in Win32ASM, using DirectDraw as an example.


Essay

Well, in this part of the Win32 API, you will soon find out how important it is to know C and C++ when you want to use an API written in these languages. Judging from the demand for this essay, I think it will be necessary to explain a bit of how objects work in C++. I will not go too deep, but only show the things you need to know in Win32ASM.

What are objects really?

Actually a structure is an object of which all fields are public. We will look at it the other way around. So the public fields in an object make up a structure. The other fields in an object are private and are not reachable from the outside. So they are not interesting to us.

A special thing about objects is that they can contain pointers to functions. Normally, when using C or ASM, this would be possible, but a bit error-prone. It can be seen as 'dirty' programming. That's why you probably haven't seen it before.

When using C++ with a compiler, there will be no errors, as long as the compiler does its job. So here you can use this technique with no chance of errors, and it gives you some nice new programming options.

C++ goes even further with this 'structure of functions' idea. With inheritance, you can also overwrite functions of the base class in the inherited class. You can also create 'virtual' functions, which are defined in the base class, but the actual code is only in inherited classes.

This is of course interesting for DirectX, where you want to have standard functions, but with different code, depending on the hardware on which it is running. So in DirectX, all functions are defined as virtual, and the base class is inherited by hardware-specific drivers which supply hardware-specific code. And the beauty of this is, that it's all transparent to the programmer. The function pointers can change at runtime because of this system, so the C++ designers had to think of a way to keep the pointers to the functions available to the program at all time.

What this all boils down to is that there is a table with pointers to the functions. It's called the Virtual Function Table. I will call this the vtable from now on.

So we need to get this table, in order to call functions from our object. Lucky for you, Z-Nith has already made a C program to 'capture' the table, and converted the resulting header file to an include file for use with MASM. So I'll just explain how you should use this table, and you can get going soon.

Well, actually it's quite simple. The DirectX objects are defined like this:

IDirectDraw STRUC
lpVtbl DWORD ?
IDirectDraw ENDS

IDirectDrawPalette STRUC
lpVtbl DWORD ?
IDirectDrawPalette ENDS

IDirectDrawClipper STRUC
lpVtbl DWORD ?
IDirectDrawClipper ENDS

IDirectDrawSurface STRUC
lpVtbl DWORD ?
IDirectDrawSurface ENDS

So these structs are actually just a pointer to the vtables, and don't contain any other values. Well, this makes it all very easy for us then. I'll give you a small example:

Say we have an IDirectDraw object called lpDD. And we want to call the RestoreDisplayMode function. Then we need to do 2 things:

1. Get the vtable.
2. Get the address of the function, using the vtable.

The first part is simple. All the struct contains, is the pointer to the vtable. So we can just do this:

mov eax, [lpDD]
mov eax, [eax]

Simple, isn't it? And the next part isn't really much harder. The vtable is put into a structure called IDirectDrawVtbl in DDRAW.INC. We now have the address of the structure in eax. All we have to do now, is get the correct member of that structure, to get the address of the function we want to call. You would have guessed by now, that this will do the trick:

call [IDirectDrawVtbl.RestoreDisplayMode][eax]

That is not a bad guess... But there's one more thing, which is very important: this function needs to be invoked on the IDirectDraw object. We may only see the vtable in the structure, but there are also private members inside the object. So there's more than meets the eye here. What it comes down to is that the call needs the object as an argument. And this will be done by stack as always. So we just need to push lpDD before we call. The complete call will look like this:

push [lpDD]
call [IDirectDrawVtbl.RestoreDisplayMode][eax]

Simple, was it not? And calls with arguments are not much harder. Let's set the displaymode to 320x200 in 32 bits next. This call requires 3 arguments:

SetDisplayMode( width, height, bpp );

Well, the extra arguments work just like normal API calls: just push them onto the stack in backward order. So it will look like this:

push 32
push 200
push 320
mov eax, [lpDD]
push eax
mov eax, [eax]
call [IDirectDrawVtbl.SetDisplayMode][eax]

And that's all there is to it.

To make life easier, we have included some MASM macros in DDRAW.INC, for use with the IDirectDraw and IDirectDrawSurface objects:

DDINVOKE MACRO func, this, arglist :VARARG
mov eax, [this]
mov eax, [eax]

IFB <arglist>
INVOKE [IDirectDrawVtbl. func][eax], this
ELSE
INVOKE [IDirectDrawVtbl. func][eax], this, arglist
ENDIF
ENDM

DDSINVOKE MACRO func, this, arglist :VARARG
mov eax, [this]
mov eax, [eax]

IFB <arglist>
INVOKE [IDirectDrawSurfaceVtbl. func][eax], this
ELSE
INVOKE [IDirectDrawSurfaceVtbl. func][eax], this, arglist
ENDIF
ENDM

With these macros, our 2 example calls will look as simple as this:

DDINVOKE RestoreDisplayMode, lpDD

DDINVOKE SetDisplayMode, lpDD, 320, 200, 32

Well, that's basically all there is to know about using objects, COM and DirectX in Win32ASM. Have fun with it!


Note Finali

And remember: C and C++ knowledge is power!

X-Calibre


Disclaimer

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevoli e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.