1

yop,


Je code un truc qui accède à des fichiers un peu partout, en ram, en flash, dans différents répertoires, et ces fichiers sont ou passés en arguments, ou découverts durant l'exécution du programme. Bref, ils peuvent être n'importe où. Evidemment, il faut que je garde une trace des fichiers : "où est le fichier que j'ai utilisé tout à l'heure ?"

La réponse, malheureusement, me semble être "sans le chemin complet, tu perdras ton fichier". Le but étant d'éviter d'utiliser SymFindFirst/SymFindNext parce que c'est bien lourd. Faisons le tour des possibilités :

1. On garde le handle du fichier pour l'identifier. Ca semble attractif, l'identifiant étant absolument unique. Oui, mais problème : impossible de retrouver facilement le nom complet du fichier. kernel::Hd2Sym renvoie une SYM_ENTRY*. Donc si on veut savoir à quel répertoire ça appartient, c'est mort. En effet, une SYM_ENTRY ne donne aucun renseignement sur le répertoire, ce n'est en effet pas un HSym. Et plein de fonctions de vat.h fonctionnent avec une SYM_STR, ce qui impose de connaitre le répertoire si on est pas dans le répertoire courant

2. On garde un HSym. Ca a l'air parfait comme ça, mais dès qu'on ajoute ou supprime un fichier dans le répertoire contenant un fichier dont on a le HSym, ce dernier devient invalide, ce qui se produit sans cesse dans mon programme. Donc exit le HSym, fausse bonne idée.

3. On garde le nom complet. Là, ça marche. Mais ça veut dire qu'à chaque fois que le programme ouvre un fichier dont il trouve le nom ici où là, il doit vérifier s'il y a un chemin, au cas où il n'y en a pas, y concaténer le répertoire courant (ou un autre, genre, euh, include ou obj par exemple), et ensuite faire des SymFindPtr. C'est coûteux en plus d'être la solution la plus chiante à mettre en place.

4. J'ai cherché aussi un moyen simple en stockant les handles des répertoires et des fichiers, puis en reconstruisant tout ça à coup de tios::SymFindHome / kernel::Hd2Sym, mais encore une fois c'est pas simple, ça double le travail d'enregistrement des références d'un fichier, et c'est aussi chiant à accéder

5. On utilise le ramcall char* kernel::Hd2FullPath (HANDLE hd, char* buffer). Et là, c'est la fin des emmerdes. Encore une fois, le kernel fait tout, mais ça on le savait déjà. smile



Exemple concret de cas où ça fait bien chier :

On lance un programme, au pif as abc def ghi\abc
Si on ne retiens les handle, la solution qui parait donc la meilleure, on a en fait deux fichiers "abc" avec deux répertoires différents. Hors quand on va vouloir accéder à ghi\abc, on va faire quoi ? kernel::Hd2Sym(Handle). Le problème, c'est que le kernel retourne alors la SYM_ENTRY, qui commence par "abc",0, et qui surtout ne donne aucun moyen de retrouver le répertoire !. Et là, quand on va faire des opérations à partir de cette chaine (comme EM_moveSymTo/FromExtMem et tant d'autres romcalls en fait), ben on va se tromper de fichier, on va travailler avec le abc du répertoire courant.


Les deux seules solutions viables consistent donc :
- soit à retenir les chemins complet : chiant pour les raisons évoquées
- soit à retenir le handle et à se taper un SymFindFirst/SymFindNext. C'est exactement le boulot que j'aimerais que le kernel fasse, en fait cheeky


Mais il y a encore une autre raison, bien plus perverse :

Je travaille avec des handles, qui peuvent appartenir subitement à des fichiers temporaires (pedrom::tmpnam) et donc à la vat, s'ils sont swappés en flash. Je n'ai aucune raison de retenir le nom de ces fichiers, vu qu'ils sont créés dans le répertoire courant, et qu'ils seront effacés avec pedrom::unlink (kernel::Hd2Sym (hd)) à la libération du handle. Le reste du temps, je me fiche de leur nom, il n'est là que pour archiver les handles.

Mais mes fonctions ne peuvent pas le deviner, ça, donc elles ne peuvent pas utiliser kernel::Hd2Sym sur n'importe quel handle, si par exemple elles veulent désarchiver un fichier. Ca marchera pour un fichier temporaire, puisque créé dans le répertoire courant, mais pas pour un "vrai fichier" qui ne sera pas effacé à la fin du programme. Au mieux, le mauvais fichier sera déswappé (et le fichier auquel on voudra accéder sera encore en fait en flash, donc on se tapera une erreur de protection), au pire le fichier ne sera pas trouvé, car dans un autre répertoire.

Et là, si je dois retenir des chemins complets pour des fichiers temporaires, alors que je ne travaille en réalité que sur les données du handle, en me foutant complètement de ce qui se passe dans la vat, je suis pas sorti de l'auberge.
Parce que évidemment, mon système de swap rend toutes ces manipulations complètement transparentes pour le core du programme (j'ai juste wrappé HeapAlloc/HeapRealloc/HeapFree), et je voudrait évidemment continuer à travailler avec des handles, surtout pas des noms de fichiers temporaires, peut-être existants, mais peut-être pas !

2

Je mets mon fichier qui gère le swap, si ça peut aider à comprendre le principe que j'utilise pour swapper et déswapper, et qui illustre bien le problème :
mem.asm
;===============================================================================
;
;	FreeObjectHandles
;
;	Free all handles used while assembling a source
;
;	in	fp	Stack frame
;
;	out	nothing
;
;	destroy	d0-d2/a0-a1
;
;===============================================================================

FreeObjectHandles:
	move.w	BIN_HD(fp),d0
	bsr	FreeHandle
	clr.w	BIN_HD(fp)

	move.w	LABELS_HD(fp),d0
	bsr.s	FreeHandle
	clr.w	LABELS_HD(fp)

	rts


;===============================================================================
;
;	FreeHandle
;
;	Free an handle, deleting the file if it belongs to one
;	Return without error if Handle is H_NULL
;
;	in	d0.w	Handle
;		fp	Stack frame
;
;	out	nothing
;
;	destroy	d0-d2/a0-a1
;
;===============================================================================

FreeHandle:
	move.w	d0,-(sp)
	beq.s	 \End
	RAMT	RAM_kernel::Hd2Sym
	move.l	a0,d0
	bne.s	\FreeFile
		ROMT	HeapFree	; No symbol associated to this handle, free it
		bra.s	\End
\FreeFile:				; A file is associated to the handle, its SYM_ENTRY is at a0
	pea	(a0)
	jsr	UNLINK(fp)
	addq.l	#4,sp
\End:	addq.l	#2,sp
	rts


;===============================================================================
;
;	AllocHandle
;
;	Allocate an handle on the heap
;	Will call NeedRAM if first attempt fails. NeedRAM checks is swapping is allowed
;	Will call MainExit if the handle could not be allocated
;
;	in	d0.l	size
;		fp	Stack frame
;
;	out	d0.w	handle
;		a0	ptr to the handle
;
;	destroy	d0-d2/a0-a1
;
;===============================================================================

AllocHandle:
	move.l	d0,-(sp)
	move.l	d0,-(sp)
	ROMT	HeapAlloc
	addq.l	#4,sp
	tst.w	d0
	bne.s	\End
		moveq.l	#0,d0		; We can archive all
		bsr	NeedRAM
		ROMT	HeapAlloc
		tst.w	d0
		bne.s	\End
			pea	StrErrorMemory(pc)
			bsr	PrintToStderr
			bra	MainExit
\End:	movea.w	d0,a0
	trap	#3
	addq.l	#4,sp
	rts


;===============================================================================
;
;	ReallocHandle
;
;	Reallocate an handle on the heap
;
;	SwapOut is automatically called for this handle
;	Call NeedRAM if first attempt fails. NeedRAM checks is swapping is allowed
;	Call MainExit if the handle could not be allocated
;
;	in	d0.l	size
;		d1.w	handle
;		fp	Stack frame
;
;	out	d0.w	handle
;		a0	ptr to the handle
;
;	destroy	d0-d2/a0-a1
;===============================================================================

ReallocHandle:
	move.l	d0,-(sp)
	move.w	d1,-(sp)
	move.l	d0,-(sp)
	move.w	d1,-(sp)

	move.w	d1,d0
	bsr	SwapOut

	ROMT	HeapRealloc
	addq.l	#6,sp
	tst.w	d0
	bne.s	\End
		move.w	(sp),d0		; This handle musn't be swapped !
		bsr	NeedRAM
		ROMT	HeapRealloc
		tst.w	d0
		bne.s	\End
			pea	StrErrorMemory(pc)
			bsr	PrintToStderr
			bra	MainExit
\End:	movea.w	d0,a0
	trap	#3
	addq.l	#6,sp
	rts


;===============================================================================
;
;	NeedRAM
;
;	Swap all possible data in flash, if allowed by the flags
;	This function is called only by AllocHandle and ReallocHandle
;	It won't throw an error if nothing can be swapped, calling functions will do that
;
;	in	d0.w	Handle which musn't be swapped (in case of reallocation)
;		fp	Stack frame
;
;	out	nothing
;
;	destroy	nothing
;
;===============================================================================

NeedRAM:
	movem.l	d0-d3/a0-a1,-(sp)
	move.w	d0,d3

	;----------------------------------------------------------------------
	;	Check if swapping is allowed
	;----------------------------------------------------------------------

	movea.l	CURRENT_FLAGS_PTR(fp),a0
	move.l	(a0),d0
	btst.l	#BIT_SWAP,d0
	beq.s	\End

	;----------------------------------------------------------------------
	;	Try to swap all availables handles
	;	It doesn't matter if all files are not really put in flash, the
	;	next (re)allocation will fail, that's all.
	;	So don't throw an error if it fails.
	;----------------------------------------------------------------------

	move.w	FILES_LIST_HD(fp),d0
	bsr.s	\SwapIn			; SwapIn () needs the Z-Flag to be set, so don't change that !

	move.w	BIN_HD(fp),d0
	bsr.s	\SwapIn

	move.w	LABELS_HD(fp),d0
	bsr.s	\SwapIn

\End:	movem.l	(sp)+,d0-d3/a0-a1
	rts


;-------------------------------------------------------------------------------
;	Swap a file :
;	- chekc that the handle exists
;	- check that the handle mustn't be kept in RAM
;	- 	get a tmp filename if the handle doesn't belong to a file
;	- 	create a file and give it the handle
;	- archive the file
;
;	This function is called only by NeedRAM
;-------------------------------------------------------------------------------

\SwapIn:
	beq.s	\NoSwapIn			; Handle not created yep (Z-flag already set)
	cmp.w	d0,d3				; Handle currently reallocated : don't swap it
	beq.s	\NoSwapIn
		RAMT	RAM_kernel::Hd2Sym									; ON VA PAS FORCEMENT ARCHIVER LE BON FICHIER !
		move.l	a0,d1
		bne.s	\ArchiveFile		; Handle already belongs to a file
			move.w	d0,-(sp)	; Save Hd
			suba.l	a0,a0		; Use PedroM internal buffer
			jsr	TMPNAM(fp)	; We don't care about the filename itself and don't have to save it
			move.w	(sp)+,d0	; Hd
			pea	(a0)		; Save filename
			jsr	CREATE_FILE(fp)
			movea.l	(sp)+,a0	; Filename
			tst.w	d0
			bne.s	\ArchiveFile
\NoSwapIn:
	rts

\ArchiveFile:
	jmp	ARCHIVE_FILE(fp)


;===============================================================================
;
;	SwapOut
;
;	Swap an handle in RAM. If it fails, call NeedRAM, then retry.
;	If it fails again, throw an error and call Main Exit
;
;	in	d0.w	Handle which must be swapped in RAM
;		fp	Stack frame
;
;	out	nothing
;
;	destroy	nothing
;
;===============================================================================

SwapOut:
	movem.l	d0-d3/a0-a2,-(sp)

	move.w	d0,d3
	RAMT	RAM_tios::ROM_base
	movea.l	a0,a2

	;----------------------------------------------------------------------
	;	Check if the file is already in RAM
	;----------------------------------------------------------------------

	movea.w	d3,a0
	trap	#3
	cmpa.l	a0,a2
	bhi.s	\End			; Already in RAM

	;----------------------------------------------------------------------
	;	Try to put the file in RAM
	;----------------------------------------------------------------------

	move.w	d3,d0
	RAMT	RAM_kernel::Hd2Sym	; Get filename in a0
	jsr	UNARCHIVE_FILE(fp)						; C'est probablement un fichier inexistant ici, ou un autre fichier qu'on va déswapper !!!
	tst.w	d0
	bne.s	\End			; Success

	;----------------------------------------------------------------------
	;	First fail. Call NeedRAM and retry
	;----------------------------------------------------------------------

	bsr	NeedRAM			; d0 already set to 0
	move.w	d3,d0
	RAMT	RAM_kernel::Hd2Sym	; Get filename in a0
	jsr	UNARCHIVE_FILE(fp)						; Pareil ici, et donc ça va foirer
	tst.w	d0
	bne.s	\End			; Success

	;----------------------------------------------------------------------
	;	Second fail. Throw an error and quit
	;----------------------------------------------------------------------

	pea	StrErrorMemory(pc)
	bsr	PrintToStderr
	moveq.l	#ERROR_MEMORY,d7
	bra	MainExit

	;----------------------------------------------------------------------
	;	Success
	;----------------------------------------------------------------------

\End:	movem.l	(sp)+,d0-d3/a0-a2
	rts

3

Pour le second cas, peux-tu réellement te retrouver à court de RAM au point d'avoir besoin de recourir à des fichiers temporaires en flash ? Ça use la puce mémoire et c'est pas top pour les perfs. Dans ce cas-là, perso je renverrais plutôt un message d'erreur et laisserais l'utilisateur archiver des choses lui-même pour faire de la place.

(ou alors tu utilises tellement de mémoire que la RAM ne suffit plus, mais je te connais, c'est pas ton genre grin)
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

4

En fait, c'est prévu pour pour des cas absolument extrêmes, genre assembler PedroM oncalc ou assimilé grin
Ceci dit :
- mon programme est optimisé pour la place consommée au run time (genre un symbole prend 4 octets, numéro de fichier ouvert + offset), quitte à être un veau question vitesse. En asm, ça reste malgré tout largement suffisant, et pratiquement transparent pour les programmes de taille usuelle. Donc avant d'utiliser la flash, il faut y aller
- le swap n'est utilisé qu'à la demande, mon programme ne peut pas être par défaut compilé avec, son activation nécessite l'emploi d'une option longue, et fait l'objet de l'affichage d'un warning.
NeedRAM:
	movem.l	d0-d3/a0-a1,-(sp)
	move.w	d0,d3

	;----------------------------------------------------------------------
	;	Check if swapping is allowed
	;----------------------------------------------------------------------

	movea.l	CURRENT_FLAGS_PTR(fp),a0
	move.l	(a0),d0
	btst.l	#BIT_SWAP,d0
	beq.s	\End

5

C'est ceci que tu veux ?
int kernel__hd2full(HANDLE h, char buffer[18])
{
  const char *name = kernel__Hd2Sym(h);
  if (name == NULL)
    return -1;
  HANDLE h_folder = kernel__Ptr2Hd(name);
  if (h_folder < 0)
    return -2;
  const char *folder = kernel__Hd2Sym(h_folder);
  if (folder == NULL)
    return -3;
  sprintf (buffer, "%s\%s", folder, name);
  return 0;
}

6

Aaaaaaaaaaaah, tu récupères le handle du répertoire, et donc son nom, en faisant un Ptr2Hd sur la SYM_ENTRY du fichier, très joli !!! top
J'avais pas trouvé d'autre solution que de faire un lookup de la VAT, mais ce que tu fais es bien plus simple, même si c'est probablement plus long en temps d'exécution.

Donc maintenant, deux solutions :
- ou tu penses que c'est une bonne chose d'ajouter un ramcall (pour faire plaisir à Zerosquare et releaser une archive -SDK, bien sûr)
- ou vu la simplicité, j'ajoute ça dans mon programme ou ma lib

Perso, la seconde solution me va très bien, sauf si tu trouves ça bien d'ajouter ça au kernel.


Par contre, comment Ptr2Hd pourrait échouer, vu qu'on sait que le folder existe, grâce au premier Hd2Sym ? Et comment le second Hd2Sym pourrait échouer, vu que on sait que la SYM_ENTRY du folder existe, si le folder existe ? Bref au pire, c'est pas grave, c'est blindé contre les VAT corrompues. smile


Merci et encore bravo pour la solution ! smile

7

Voilà, de mon côté, je pensais à ça en fait :
short kernel__hd2full(HANDLE h, char buffer[18])
{
    SYM_ENTRY* se;

    SymFindFirst (NULL, FO_RECURSE);

    do
    {
        se = SymFindNext ();

        if (!se)
            return 0;

    } while (se.handle != h);

    return sprintf (buffer, "%s\%s", SymFindFolderName (), se);
}

Ca me parait plus rapide, et la validité du résultat est garantie par le TIOS, il n'y a qu'une erreur possible (le handle n'appartient pas à un fichier, ou n'est pas alloué).
En effet, les deux kernel::Hd2Sym font chacun un SymFindFirst/SymFindNext, et le kernel::Ptr2Hd fait carrément un lookup de la table des handles, avec calcul de l'adresse de fin du handle.

8

Je ne vois pas la plus value du kernel là. Il offre déjà toutes les fonctions à l'utilisateur. Ca serait mieux dans ton programme je pense wink

9

Folco (./7) :
short kernel__hd2full(HANDLE h, char buffer[18])
{
    SYM_ENTRY* se = SymFindFirst (NULL, FO_RECURSE);

    while (se != NULL && se->handle != h);
    {
        se = SymFindNext ();
    }
    if (se == NULL)
       return 0;
    return sprintf (buffer, "%s\%s", SymFindFolderName (), se);
}

Fixed

Ca me parait plus rapide, et la validité du résultat est garantie par le TIOS, il n'y a qu'une erreur possible (le handle n'appartient pas à un fichier, ou n'est pas alloué).
En effet, les deux kernel::Hd2Sym font chacun un SymFindFirst/SymFindNext, et le kernel::Ptr2Hd fait carrément un lookup de la table des handles, avec calcul de l'adresse de fin du handle.

Ouep.

10

Ok, c'est juste que c'est une fonction qui peut être utile, et juste un poil chiante à écrire. J'ai trop tendance à considérer le kernel comme une lib couteau suisse en fait, à force de le savourer grin Mais je pense que t'as raison. smile

(erf, sacré . au lieu de -> sick. Sinon, c'est pas la peine de tester le retour de SymFindFirst, c'est forcément un répertoire, en FO_RECURSE, je me trompe ?)

J'ai déjà la version asm, je l'intègre à ma lib :
pdtlib::GetFullName:
	movem.l	d1-d3/a0-a1,-(sp)
	move.w	d0,d3

	move.w	#2,-(sp)
	clr.l	-(sp)
	ROMT	SymFindFirst
	addq.l	#6,sp

\Loop:	ROMT	SymFindNext
	move.l	a0,d0
	beq.s	\Fail
		cmp.w	12(a0),d3
		bne.s	\Loop

	pea	(a0)			; SYM_ENTRY*
	ROMT	SymFindFoldername
	pea	(a0)			; Folder*
	bsr.s	\Push			; Format*
	dc.b	"%s\%s",0
\Push:	move.l	24(sp),-(sp)		; Buffer*
	ROMT	sprintf
	lea	16(sp),sp

\Fail:	movem.l	(sp)+,d1-d3/a0-a1
	rts


Désolé, Zerosquare tsss

11

cry grin
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

12

Et en plus mieux bien :
pdtlib::GetFullName:
	movem.l	d1-d3/a0-a3,-(sp)
	move.w	d0,d3
	movea.l	a0,a3

	move.w	#2,-(sp)
	clr.l	-(sp)
	ROMT	SymFindFirst
	addq.l	#6,sp

\Loop:	ROMT	SymFindNext
	move.l	a0,d0
	beq.s	\Fail
		cmp.w	12(a0),d3
		bne.s	\Loop

	movea.l	a0,a2
	pea	(a0)
	ROMT	SymFindFoldername
\Dir:	move.b	(a0)+,(a3)+
	bne.s	\Dir

	move.b	#'\',-1(a3)
\File:	move.b	(a2)+,(a3)+
	bne.s	\File

\Fail:	movem.l	(sp)+,d0-d3/a0-a3
	rts

J'arriverai jamais à caler ce bsr \Push ; dc.b "..." cry

13

Ta seconde version a un bug en cas de branchement vers \Fail (pile)
smile

14

Ouep. En fait elle est foireuse cette version, pour 0 octets de moins. Ya un autre bug, c'est que je me sers du a0 pushé pour SymFindFoldername pour écrire la valeur de retour dans d0.l. Mais même si ce romcall, a priori, ne doit pas faire autre chose que charger une adresse dans a0, il peut potentiellement effacer (sp), ce qui fait que ma fonction paraitrait avoir foiré alors qu'elle aurait réussi.

Donc je garde mon bsr.s \Push ! \o/ grin

15

Nouvelle variante (gain de place) :

short GetFullName (HANDLE h, char Buffer [18])
{
    SYM_ENTRY* se = kernel__Hd2Sym (h);
    return (se ? sprintf (buffer, "%s\%s", SymFindFolderName (), se) : 0);
}


Seulement, la doc dit ça : Warning: It may use internally SymFindFirst / SymFindNext.
Alors que c'est toujours le cas, le code est quasi identique à ma version asm (sauf que tu testes la première SYM_ENTRY retournée pour ne pas rater le premier répertoire). Hors Il faudrait que ce soit sûr pour pouvoir utiliser sans souci SymFindFolderName.

Vu que ça ne risque pas de changer, c'est possible de le garantir pour ne pas réimplémenter Hd2Sym ? smile

16

Je ne sais pas. Il faudrait un faire un sondage des utilisateurs kernels pour voir si ca serait génant. smile

17

Donc tu sais en fait, 100% sont d'accord. grin

Faisons un sondage, pour la forme :

18

Oh ! On devrait interdire aux googlebots de voter, ils ne savent pas de quoi il retourne embarrassed

19

Mais non c'est moi qui ai voulu empecher un score de république bananière tongue
avatar

20

Oh, traitre ! Je te prends en 1v1 quand tu veux !!!

Quoi qu'il en soit, on constate que l'intégralité de la communauté, à l'exception du petit plaisantin du post précédent, se prononce en faveur de la modification de la doc. Devant ce raz-de-marée démocratique (car il est bien entendu que le design d'un kernel est une question profondément démocratique embarrassed), PpHd privilégiera sans aucun doute la solution plébiscitée par ses innombrables utilisateurs ! smile

21

grin
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

22

(tiens, on a fait un tour de compteur, il y a 2^32 + 3 utilisateurs favorables. Faudrait voir à modifier les compteurs des sondages, Bob !)

23

(grin)

24

(non C'est pas bien de mentir.)

25

(il a rien dit Pen^2 confus)

26

(mais j'ai voté oui tripo)

27

Heureusement pour toi fouet
avatar
<<< Kernel Extremis©®™ >>> et Inventeur de la différence administratif/judiciaire ! (©Yoshi Noir)

<Vertyos> un poil plus mais elle suce bien quand même la mienne ^^
<Sabrina`> tinkiete flan c juste qu'ils sont jaloux que je te trouve aussi appétissant

28

grin

29

hmmm, j'ai un gros doute...

Dans ton ./9, tu fais un sprintf avec des SYM_ENTRY. Or une SYM_ENTRY c'est ça :
typedef struct
{
	char name[8]; 
	unsigned short compat; 
	union
	{
		unsigned short flags_n; 
		struct
		{ 
			unsigned int busy : 1, local : 1, flag1_5 : 1, flag1_4 : 1, collapsed : 1, twin : 1, archived : 1, in_view : 1; 
			unsigned int folder : 1, overwritten : 1, checked : 1, hidden : 1, locked : 1, statvar : 1, graph_ref_1 : 1, graph_ref_0 : 1; 
		} bits; 
	} flags; 
	HANDLE handle; 
} SYM_ENTRY;

Rien ne dit que le nom se termine par un 0, non ? Ca ne marchera pas avec une vat corrompue j'imagine ?
Parce que même si compat c'est ça : enum CompatFlags {CF_NONE = 0, CF_CONVERT = 1, CF_ENHANCED = 2, CF_NEW = 3};, c'est quand même stocké sur le short qui suit le champs name. Merci TI de pas avoir consacré l'octet qui sert à rien au 0 final. couic

Donc, la question : est-ce fiable ? Oui ou non ?

30

Tu veux une réponse théorique ou pratique ?