Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Bonjour,
Je fais appel à un objet COM.
Tous mes appels de méthodes fonctionnent correctement sauf un, et je ne parviens pas à trouver la solution.
Voici l'en-tête de la méthode de l'objet :
void GetDecryptedFile(unsigned char** ppbFileContents);
Voici mon appel depuis PowerBuilder :
string ls_content ioo_my_ole_object.GetDecryptedFile(ref ls_content)
Et là ça crash avec une erreur R0035 : "Error: Error calling external function GetDecryptedFile at line ... in ... event of object ..."
Je pense donc qu'il s'agit d'un problème de paramètre, et je ne vois pas la solution. Je dispose de la longueur de la chaine de caractère qui doit être assignée par GetDecryptedFile(), peut-être que ça peut aider ?
Je vous remercie, encore une fois, pour votre aide !
Dernière modification par Nyphel (01-10-2008 07:52:11)
Hors ligne
Nyphel a écrit:
Je dispose de la longueur de la chaine de caractère qui doit être assignée par GetDecryptedFile(), peut-être que ça peut aider ?
Peut-être... L'idéal serait de jeter un oeil sur la doc de l'API dont ce GetDecryptedFile fait partie...
En attendant, je vois 2 choses à tester:
1 - comme tu connais la longueur de la chaine qui doit etre assignée, initialise ta variable string avec
string ls_content ls_content = space(x) // avec x la longeur à utiliser ioo_my_ole_object.GetDecryptedFile(ls_content) // Ne met pas de 'ref' lors de l'appel, j'ose espérer que // c'était une faute de frappe de ta part ;)
Souvent, ce genre d'API bas niveau ne prennent pas le temps d'initialiser l'espace mémoire des variables qu'ils sont sensé utiliser, partant du principe que cela doit déjà avoir été fait.
2 - Comme on a affaire à un pointeur de pointeur, ça me fait penser à un souci que j'ai trop souvent rencontré. Essaye ce qui suit:
string ls_content long ll_content ioo_my_ole_object.GetDecryptedFile(ll_content) if ll_content > 0 then ls_content = string(ll_content, 'address') end if
Hors ligne
Bonjour Cortex, et merci pour ta réponse !
A vrai dire le 'ref' était intentionnel, puisque je pensais devoir passer un pointeur sur ma variable... Mais je sens que j'ai mal compris les choses .
Par contre je ne dispose pas vraiment de documentation en ce qui concerne la méthode, j'en ai demandé tout à l'heure mais bon... Je ne suis pas certain d'obtenir quoi que ce soit de concluent.
J'ai testé les deux solutions proposées, et toutes deux me retournent le même message d'erreur que précédemment ("Error: Error calling external function GetDecryptedFile at line ... in ... event of object ..."). Autant je comprends bien l'idée de la première solution, autant j'ai du mal à saisir la seconde. La méthode me retournerait en fait l'adresse pointée par le premier pointeur ?
Hors ligne
Nyphel a écrit:
Autant je comprends bien l'idée de la première solution, autant j'ai du mal à saisir la seconde. La méthode me retournerait en fait l'adresse pointée par le premier pointeur ?
Pour info alors (puisque ca ne corrige pas ton problème), il arrive parfois que certains outils de dev (souvent PB et VB6.0), suite à une particularité de leur gestion mémoire, aient du mal sur certaines variables de type tableau de char (le cas ici) ou des tableaux de structures complexes. J'ai par exemple eu le coup dans des API pour imprimantes, quand on veut récupérer la liste des imprimantes installées, etc...
Le but du code est en effet de récupérer le pointeur de la chaine produite par ton API, et de demander à PB de la convertir en string... Mais c'est quand même assez dangereux, faut pas commencer à jouer dans PB avec ce pointeur ;)
Et pour en revenir à ton problème, sans doc, il y a peu de chance de trouver ce qui cloche...
Hors ligne
J'ai pu obtenir de la documentation sur le sujet, et il m'est demandé d'utiliser la fonction DecryptAESFile(...) d'une DLL externe, plutôt que la précédante fonction GetDecryptedFile() de l'objet COM.
La DLL que j'utilise est écrite en C, et est encodée ANSI.
DWORD DecryptAESFile(IN char * szFilePath, OUT UCHAR ** ppcDecryptedData, OUT DWORD * pdwDecryptedSize)
- Decrypt the aes-encrypted file (defined with szFilePath) into the ppcDecryptedData buffer of size equal to pdwDecryptedSize.
Je déclare donc ma fonction externe comme suit :
FUNCTION long DecryptAESFile(string szInputFile, ref string pcDecryptedFileContents, ref ULong dwDecryptedContentsSize) LIBRARY "Csr_PicDEC.dll" alias for "_DecryptAESFile@12;Ansi"
Puis je l'utilise comme ceci :
string ls_test_encrypted_picture, ls_test_DecryptedContents ULong ll_test_DecryptedContentsSize blob lb_test_decrypted_content ls_test_encrypted_picture = "C:\CSR\EXE\2-encrypted.jpg" // Décrypte le contenu d'un fichier image crypté // ls_test_DecryptedContents est géré par la fonction (allocation de mémoire, affectation du contenu texte décrypté), // ll_test_DecryptedContentsSize : longueur du texte décrypté DecryptAESFile(ls_test_encrypted_picture, ls_test_DecryptedContents, ll_test_DecryptedContentsSize) messagebox('1', string(ll_test_DecryptedContentsSize)) // Me retourne 7200 messagebox('2', string(ls_test_DecryptedContents)) // Me retourne 4 caractères bizarres et aléatoires // Affichage de l'image dans un PictureControl lb_test_decrypted_content = blob(ls_test_DecryptedContents) p_test.setpicture(lb_test_decrypted_content) // Enregistrement de l'image décryptée dans un fichier integer li_FileNum li_FileNum = FileOpen("D:\PICTURE.JPG", LineMode!, Write!, LockWrite!, Replace!) FileWrite(li_FileNum, ls_test_DecryptedContents) FileClose(li_FileNum)
Il semblerait donc que j'accède bien à la fonction de ma DLL.
Cette dernière décrypte correctement l'image puisqu'elle me retourne la longueur de la chaine décryptée (7200).
En revanche je n'accède pas correctement au résultat, on dirait que j'accède au pointeur...
J'avoue que j'ai du mal à ce niveau. Une idée ?
Dernière modification par Nyphel (04-11-2008 17:13:17)
Hors ligne
Bonjour,
Tu as la réponse dans une autre de tes discussions : http://pbadonf.fr/forum/viewtopic.php?id=1956
A mon point de vue : uchar ** => ref byte ppcDecryptedData[]
Si byte est indisponible sur ta version, tu peux utiliser long à la place http://www.sybase.com/detail?id=44648.
Hors ligne
Bonjour Buck, et merci pour ce rappel. Bien que j'essaie de reprendre les posts de façon aussi claire que possible, je m'y perds parfois moi-même
Le type Byte est en effet indisponible sur ma version, et les tableaux de long/char n'apportent pas plus de résultats.
Essai n°1 : j'obtiens une série de 8 chiffres dans ll_test_DecryptedContents
FUNCTION long DecryptAESFile(string szInputFile, ref long pcDecryptedFileContents[], ref ULong dwDecryptedContentsSize) LIBRARY "Csr_PicDEC.dll" alias for "_DecryptAESFile@12;Ansi"
string ls_test_encrypted_picture, ls_test_DecryptedContents ULong ll_test_DecryptedContentsSize long ll_test_DecryptedContents[] char lc_test_DecryptedContents[] ls_test_encrypted_picture = "C:\CSR\EXE\2-encrypted.jpg" // Décrypte le contenu d'un fichier image crypté // ls_test_DecryptedContents est géré par la fonction (allocation de mémoire, affectation du contenu texte décrypté), // ll_test_DecryptedContentsSize : longueur du texte décrypté DecryptAESFile(ls_test_encrypted_picture, ll_test_DecryptedContents, ll_test_DecryptedContentsSize)
Essai n°2 : j'obtiens quelques étranges caractères dans lc_test_DecryptedContents
FUNCTION long DecryptAESFile(string szInputFile, ref char pcDecryptedFileContents[], ref ULong dwDecryptedContentsSize) LIBRARY "Csr_PicDEC.dll" alias for "_DecryptAESFile@12;Ansi"
string ls_test_encrypted_picture, ls_test_DecryptedContents ULong ll_test_DecryptedContentsSize long ll_test_DecryptedContents[] char lc_test_DecryptedContents[] ls_test_encrypted_picture = "C:\CSR\EXE\2-encrypted.jpg" // Décrypte le contenu d'un fichier image crypté // ls_test_DecryptedContents est géré par la fonction (allocation de mémoire, affectation du contenu texte décrypté), // ll_test_DecryptedContentsSize : longueur du texte décrypté DecryptAESFile(ls_test_encrypted_picture, lc_test_DecryptedContents, ll_test_DecryptedContentsSize)
Bref j'ai l'impression que j'accède au pointeur, mais pas à la chaine pointée.
Hors ligne
et si tu fais un String( ls_chaine, 'address' )
Hors ligne
Je viens de tester cela Erasorz, mais sans succès.
Pour un paramètre de type tableau de long, alors le "String(parametre_rempli_par_DLL, 'address')" me retourne une chaine vide.
Pour un paramètre de type tableau de char, alors le "String(parametre_rempli_par_DLL, 'address')" me retourne "address".
Pour un paramètre de type string, alors le "String(parametre_rempli_par_DLL, 'address')" me retourne "address".
Hors ligne
Bonjour,
Il faut peut être réserver l'espace mémoire avant d'appeler la fonction.
Pour faire un test :
ll_test_DecryptedContents[10000] = 0
Hors ligne
Que mes tableaux soient initialisés ou pas, j'obtiens les mêmes résultats.
Idem lorsque j'utilise "String(parametre_rempli_par_DLL, 'address')".
:-/
Hors ligne
Je viens de relire ceci dans la documentation :
DWORD DecryptAESFile(IN char * szFilePath, OUT UCHAR ** ppcDecryptedData, OUT DWORD * pdwDecryptedSize)
- Decrypt the aes-encrypted file (defined with szFilePath) into the ppcDecryptedData buffer of size equal to pdwDecryptedSize.
Je n'avais pas pris garde au type UCHAR**, j'agissais comme si il s'agissait d'un type CHAR**.
Voici ce que dit la documentation MSDN au sujet du type UCHAR :
A UCHAR is an 8-bit integer with the range: 0 through 255 decimal. Because a UCHAR is unsigned, its first bit (Most Significant Bit (MSB)) is not reserved for signing.
Je ne comprends pas la logique, puisque l'objectif de cette fonction est de me retourner le contenu texte d'une image JPEG décryptée : ce texte devrait certainement être codable sur 7 bits, donc sur du char, si il utilise les normes classiques. En tous cas il semblerait que Powerbuilder n'aie pas de type équivalant au UChar*.
Je vais essayer d'obtenir plus d'informations sur le sujet.
Dernière modification par Nyphel (06-11-2008 08:47:23)
Hors ligne