magic_Nono
Messages postés1878Date d'inscriptionjeudi 16 octobre 2003StatutMembreDernière intervention16 mars 2011
-
18 déc. 2004 à 09:00
cs_supergrey
Messages postés475Date d'inscriptionvendredi 27 juin 2003StatutMembreDernière intervention20 septembre 2010
-
3 juin 2010 à 10:34
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.
cs_supergrey
Messages postés475Date d'inscriptionvendredi 27 juin 2003StatutMembreDernière intervention20 septembre 2010 3 juin 2010 à 10:34
Pour info je suis sous windows 7 64, je ne trouve pas le problème...
cs_supergrey
Messages postés475Date d'inscriptionvendredi 27 juin 2003StatutMembreDernière intervention20 septembre 2010 2 juin 2010 à 18:30
Salut, merci pour la source, je viens d'essayer et le raccourcis ne pointe sur rien, voila ma fonction:
void Raccourci(char* name,char* description,char* path)
{
// Créer un buffer pour recevoir le chemin d'un dossier spécial:
char buffer[MAX_PATH];
// Initialiser la librairie COM pour notre programme:
CoInitialize(NULL);
// Déclarer un pointeur sur IShellLink:
IShellLink* psl;
// Créer une instance de l'interface IShellLink:
HRESULT res = CoCreateInstance(CLSID_ShellLink,0,CLSCTX_INPROC_SERVER,IID_IShellLink,(LPVOID *)&psl);
//Si instance créées avec succès:
if (SUCCEEDED(res))
{
// Déclarer un pointeur sur IPersistFile:
IPersistFile* ppf;
// Obtenir une interface IPersistFile:
psl->QueryInterface(IID_IPersistFile,(LPVOID *)&ppf);
// Ajout des raccourcis:
// Obtenir le chemin du dosier spécial en cours:
SHGetSpecialFolderPath(0,buffer,CSIDL_DESKTOP,0);
strcat(buffer,"\");
// Former le chemin complet de l'emplacement du raccourci:
strcat(buffer,name);
strcat(buffer,".lnk");
// Définir le chemin du raccourci:
psl->SetPath(path);
// Définir la description:
psl->SetDescription(description);
// Convertir le chemin en UNICODE:
WORD chaine[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0,buffer, -1,(LPWSTR)chaine, MAX_PATH);
// Créer le raccourci:
ppf->Save((LPWSTR)chaine, 1);
// Incrémenter le compteur de raccourcis créés:
racpp
Messages postés1909Date d'inscriptionvendredi 18 juin 2004StatutModérateurDernière intervention14 novembre 201417 22 mars 2005 à 20:01
BruNews > Merci, j'espère que "erreur 500" ne m'empechera plus de répondre aux commentaires.
cosmobob > Merci pour les remarques. En effet, lorsqu'on focalise sur le noyau d'un programme on ne fait pas très attention au reste, surtout quand on manque de temps.
A propos de la première remarque, j'avais fait "char str[30]" car le message à concaténer était " raccourci(s) créé(s)!", ce qui fait un total de 23 caractères seulement. Mais, après avoir ajouté "avec succès", j'ai oublié d'augmenter la taille du tableau str. Ca n'a pourtant pas empêché le message de s'afficher correctement (non tronqué chez moi). Si sa taille est 40 par exemple, on n'aura jamais de buffer overflow. La fonction strncat() est inutile ici puisque la taille de la chaine à concaténer est fixe. Cette fonction ne sert qu'à limiter le nombre de caractères à concaténer.
Pour la deuxième remarque, je n'ai jamais eu de plantages causés par l'absence de "const" dans le prototype de fonctions. Mais c'est bon à savoir. Merci pour le conseil.
BruNews
Messages postés21040Date d'inscriptionjeudi 23 janvier 2003StatutModérateurDernière intervention21 août 2019 21 mars 2005 à 19:12
Avec un peu de retard de ma part, bonne source.
cosmobob
Messages postés700Date d'inscriptionmardi 30 décembre 2003StatutMembreDernière intervention27 janvier 20094 23 févr. 2005 à 14:30
en l'occurence c'etait strncat qu'il eut fallu utiliser et pas strncpy ;) enfin bon, quoi qu'il arrive, mieux vaut remplacer strcpy et strcat par leurs versions avec controle de la taille de buffer, à savoir strncpy et strncat. ces erreurs la sont les plus chiantes a déboguer....
sinon, ta source est tres bien, bravo!
a++ ;)
cosmobob
Messages postés700Date d'inscriptionmardi 30 décembre 2003StatutMembreDernière intervention27 janvier 20094 23 févr. 2005 à 14:22
salut,
juste pour te dire que t'as pas fait attention ici:
char str[30];
itoa(nombre,str,10);
strcat(str," raccourci(s) créé(s) avec succès!");
(a la fin de la fonction raccourci)
et que du coup il y a un buffer overflow.
meme si on s'en rend pas bien compte, " raccourci(s) créé(s) avec succès!" fait plus que 30 caracteres.
Comme quoi mieux vaut TOUJOURS utiliser strncpy à la place de strcpy. Tu aurais vu à l'execution le message tronqué, et t'aurais compris que la taille du buffer etait trop petite.
Pis pareil, le prototype de raccourci devrait plutot etre:
int Raccourci(HWND parent, const BOOL* emplacement, const char* name, const char* description, const char* group, const char* path)
vu que ce qui est pointé par tes parametres n'a pas vocation a etre modifié. prendre l'habitude la coute rien et permet d'eviter certains plantages des la compilation.
a+
cs_Nebula
Messages postés787Date d'inscriptionsamedi 8 juin 2002StatutMembreDernière intervention 7 juin 20072 20 déc. 2004 à 18:24
D'accord, ceci explique cela. Mais les manipulations que j'ai exposées permettent une compilation en C pur, et fonctionnent à merveille (pas testé en mode C++, je ne l'utilise pour ainsi dire jamais). Encore merci pour cette source très utile !
racpp
Messages postés1909Date d'inscriptionvendredi 18 juin 2004StatutModérateurDernière intervention14 novembre 201417 20 déc. 2004 à 16:53
Salut,
Nebula > Quand j'ai commencé à faire ce source, je n'avais pas l'intention de le faire en C pur. Je n'ai donc rien changé aux options de mon compilateur (Visual C/C++ 6). D'après ces messages d'erreurs, il me semble que le compilateur doit être en mode C++. Toutes ces interfaces sont définies dans "comdef.h". Dans l'en-tête de ce fichier on peut lire:"Native C++ compiler COM support" puis un peu plus bas :
#ifndef __cplusplus
#error Native Compiler support only available in C++ compiler
#endif
Je pense que cela explique ces erreurs. En C++, tu n'auras sûrement auncun problème de compilation. Bonne chance.
cs_Nebula
Messages postés787Date d'inscriptionsamedi 8 juin 2002StatutMembreDernière intervention 7 juin 20072 20 déc. 2004 à 02:37
Excellente source (et en C, de plus), mais j'ai eu du mal à la faire fonctionner !
Tout d'abord, j'ai fait face à des erreurs de ce type :
main.c(74) : error C2039: 'QueryInterface' : is not a member of 'IShellLinkA'
C:\Program Files\Microsoft SDK\include\ShObjIdl.h(5239) : see declaration of 'IShellLinkA'
main.c(75) : error C2039: 'SetPath' : is not a member of 'IShellLinkA'
C:\Program Files\Microsoft SDK\include\ShObjIdl.h(5239) : see declaration of 'IShellLinkA'
main.c(78) : error C2039: 'Save' : is not a member of 'IPersistFile'
C:\Program Files\Microsoft SDK\include\ObjIdl.h(5492) : see declaration of 'IPersistFile'
main.c(79) : error C2039: 'Release' : is not a member of 'IPersistFile'
C:\Program Files\Microsoft SDK\include\ObjIdl.h(5492) : see declaration of 'IPersistFile'
main.c(88) : error C2039: 'Release' : is not a member of 'IShellLinkA'
C:\Program Files\Microsoft SDK\include\ShObjIdl.h(5239) : see declaration of 'IShellLinkA'
Que j'ai résolu après examen du .h incriminé, en modifiant les lignes pour utiliser la structure de l'interface, ainsi (iSL était mon IShellLink* et iPF le iPersistFile*) :
iSL->QueryInterface(IID_IPersistFile, &iPF);
iSL->SetPath(szName);
iSL->SetDescription(szDesc);
iSL->SetIconLocation(szName, 0);
Est devenu (il a fallu ajouter un & devant IID_IPersistFile et les autres IID_*, j'ignore pourquoi) :
iSL->lpVtbl->QueryInterface(iSL, &IID_IPersistFile, &iPF);
iSL->lpVtbl->SetPath(iSL, szName);
iSL->lpVtbl->SetDescription(iSL, szDesc);
iSL->lpVtbl->SetIconLocation(iSL, szName, 0);
Ensuite la compilation s'est (enfin !) bien déroulée, hormis quelques warnings et une erreur...
Sous MSVC: main.obj : error LNK2001: unresolved external symbol _IID_IPersistFile
et avec GCC: main.c:74: undefined reference to `IID_IPersistFile'
Bon après petite recherche dans les lib, il fallait linker avec uuid.lib ou libuuid.a (selon le compilo). Ce n'est pas le plus grave, j'aimerais juste savoir comment il se fait que j'aie du passer par la structure de l'interface pour compiler, aussi bien dans MSVC que MinGW ? J'ai compilé les deux en mode C "pur", et les exemples de la MSDN sont un coup avec l'interface "normale" et un coup avec l'utilisation de la structure interne, ce qui me laisse perplexe. Il y a aussi cette histoire de "&" devant les constantes IID_* :-/
Pour mon premier contact avec les interfaces, je trouve çà un peu chi*nt... Faut être obstiné, lol
XCat
Messages postés7Date d'inscriptiondimanche 28 novembre 2004StatutMembreDernière intervention19 décembre 2004 19 déc. 2004 à 11:46
cool ton prog
racpp
Messages postés1909Date d'inscriptionvendredi 18 juin 2004StatutModérateurDernière intervention14 novembre 201417 18 déc. 2004 à 13:51
Salut,
Merci pour les commentaires.
AlexMAN > Je préfère céer mes boites de dialogues dynamiquement car je n'aime pas l'éditeur de ressources. Je préfère tout mettre dans le code tant que possible. Ca me permet de le mieux maitriser. Puisque j'utilise beaucoup les boites de dialogues, je trouve plus pratique de copier/coller la portion de création de la boite que d'être obligé d'ajouter à chaque fois une nouvelle ressource. Avec la méthode dynamique, on peut définir la position et les dimensions de la boite avant sa création. Ce ne sont que des exemples d'avantages car il y'en a d'autres comme la précision, la réutilisation du code, la portabilité pour les compilateurs Windows etc...
gagah1
Messages postés509Date d'inscriptionsamedi 28 juin 2003StatutMembreDernière intervention 3 août 2010 18 déc. 2004 à 11:19
Salut!
J'ai pas encore regardé les codes mais déjà je te remercie beaucoup.
cs_AlexMAN
Messages postés1536Date d'inscriptionsamedi 21 décembre 2002StatutMembreDernière intervention24 mai 20091 18 déc. 2004 à 09:15
Bonjour,
D'abord merci pour ton prog, car c bien utile d'avoir un ptit programme comme ca !
Ensuite, j'ai une kestion :
Dans tous tes progs, tu crées des dialogs 'dynamikement', a partir de ton propre TEMPLATE, ya til une raison ou alors est ce que c juste une habitude ?
Voila, merci beaucoup
A bientot
+2(p-n)
magic_Nono
Messages postés1878Date d'inscriptionjeudi 16 octobre 2003StatutMembreDernière intervention16 mars 2011 18 déc. 2004 à 09:00
3 juin 2010 à 10:34
2 juin 2010 à 18:30
void Raccourci(char* name,char* description,char* path)
{
// Créer un buffer pour recevoir le chemin d'un dossier spécial:
char buffer[MAX_PATH];
// Initialiser la librairie COM pour notre programme:
CoInitialize(NULL);
// Déclarer un pointeur sur IShellLink:
IShellLink* psl;
// Créer une instance de l'interface IShellLink:
HRESULT res = CoCreateInstance(CLSID_ShellLink,0,CLSCTX_INPROC_SERVER,IID_IShellLink,(LPVOID *)&psl);
//Si instance créées avec succès:
if (SUCCEEDED(res))
{
// Déclarer un pointeur sur IPersistFile:
IPersistFile* ppf;
// Obtenir une interface IPersistFile:
psl->QueryInterface(IID_IPersistFile,(LPVOID *)&ppf);
// Ajout des raccourcis:
// Obtenir le chemin du dosier spécial en cours:
SHGetSpecialFolderPath(0,buffer,CSIDL_DESKTOP,0);
strcat(buffer,"\");
// Former le chemin complet de l'emplacement du raccourci:
strcat(buffer,name);
strcat(buffer,".lnk");
// Définir le chemin du raccourci:
psl->SetPath(path);
// Définir la description:
psl->SetDescription(description);
// Convertir le chemin en UNICODE:
WORD chaine[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0,buffer, -1,(LPWSTR)chaine, MAX_PATH);
// Créer le raccourci:
ppf->Save((LPWSTR)chaine, 1);
// Incrémenter le compteur de raccourcis créés:
// Libérer l'interface IPersistFile:
ppf->Release();
}
psl->Release();
CoUninitialize();
}
22 mars 2005 à 20:01
cosmobob > Merci pour les remarques. En effet, lorsqu'on focalise sur le noyau d'un programme on ne fait pas très attention au reste, surtout quand on manque de temps.
A propos de la première remarque, j'avais fait "char str[30]" car le message à concaténer était " raccourci(s) créé(s)!", ce qui fait un total de 23 caractères seulement. Mais, après avoir ajouté "avec succès", j'ai oublié d'augmenter la taille du tableau str. Ca n'a pourtant pas empêché le message de s'afficher correctement (non tronqué chez moi). Si sa taille est 40 par exemple, on n'aura jamais de buffer overflow. La fonction strncat() est inutile ici puisque la taille de la chaine à concaténer est fixe. Cette fonction ne sert qu'à limiter le nombre de caractères à concaténer.
Pour la deuxième remarque, je n'ai jamais eu de plantages causés par l'absence de "const" dans le prototype de fonctions. Mais c'est bon à savoir. Merci pour le conseil.
21 mars 2005 à 19:12
23 févr. 2005 à 14:30
sinon, ta source est tres bien, bravo!
a++ ;)
23 févr. 2005 à 14:22
juste pour te dire que t'as pas fait attention ici:
char str[30];
itoa(nombre,str,10);
strcat(str," raccourci(s) créé(s) avec succès!");
(a la fin de la fonction raccourci)
et que du coup il y a un buffer overflow.
meme si on s'en rend pas bien compte, " raccourci(s) créé(s) avec succès!" fait plus que 30 caracteres.
Comme quoi mieux vaut TOUJOURS utiliser strncpy à la place de strcpy. Tu aurais vu à l'execution le message tronqué, et t'aurais compris que la taille du buffer etait trop petite.
Pis pareil, le prototype de raccourci devrait plutot etre:
int Raccourci(HWND parent, const BOOL* emplacement, const char* name, const char* description, const char* group, const char* path)
vu que ce qui est pointé par tes parametres n'a pas vocation a etre modifié. prendre l'habitude la coute rien et permet d'eviter certains plantages des la compilation.
a+
20 déc. 2004 à 18:24
20 déc. 2004 à 16:53
Nebula > Quand j'ai commencé à faire ce source, je n'avais pas l'intention de le faire en C pur. Je n'ai donc rien changé aux options de mon compilateur (Visual C/C++ 6). D'après ces messages d'erreurs, il me semble que le compilateur doit être en mode C++. Toutes ces interfaces sont définies dans "comdef.h". Dans l'en-tête de ce fichier on peut lire:"Native C++ compiler COM support" puis un peu plus bas :
#ifndef __cplusplus
#error Native Compiler support only available in C++ compiler
#endif
Je pense que cela explique ces erreurs. En C++, tu n'auras sûrement auncun problème de compilation. Bonne chance.
20 déc. 2004 à 02:37
Tout d'abord, j'ai fait face à des erreurs de ce type :
main.c(74) : error C2039: 'QueryInterface' : is not a member of 'IShellLinkA'
C:\Program Files\Microsoft SDK\include\ShObjIdl.h(5239) : see declaration of 'IShellLinkA'
main.c(75) : error C2039: 'SetPath' : is not a member of 'IShellLinkA'
C:\Program Files\Microsoft SDK\include\ShObjIdl.h(5239) : see declaration of 'IShellLinkA'
main.c(78) : error C2039: 'Save' : is not a member of 'IPersistFile'
C:\Program Files\Microsoft SDK\include\ObjIdl.h(5492) : see declaration of 'IPersistFile'
main.c(79) : error C2039: 'Release' : is not a member of 'IPersistFile'
C:\Program Files\Microsoft SDK\include\ObjIdl.h(5492) : see declaration of 'IPersistFile'
main.c(88) : error C2039: 'Release' : is not a member of 'IShellLinkA'
C:\Program Files\Microsoft SDK\include\ShObjIdl.h(5239) : see declaration of 'IShellLinkA'
Que j'ai résolu après examen du .h incriminé, en modifiant les lignes pour utiliser la structure de l'interface, ainsi (iSL était mon IShellLink* et iPF le iPersistFile*) :
iSL->QueryInterface(IID_IPersistFile, &iPF);
iSL->SetPath(szName);
iSL->SetDescription(szDesc);
iSL->SetIconLocation(szName, 0);
Est devenu (il a fallu ajouter un & devant IID_IPersistFile et les autres IID_*, j'ignore pourquoi) :
iSL->lpVtbl->QueryInterface(iSL, &IID_IPersistFile, &iPF);
iSL->lpVtbl->SetPath(iSL, szName);
iSL->lpVtbl->SetDescription(iSL, szDesc);
iSL->lpVtbl->SetIconLocation(iSL, szName, 0);
Ensuite la compilation s'est (enfin !) bien déroulée, hormis quelques warnings et une erreur...
Sous MSVC: main.obj : error LNK2001: unresolved external symbol _IID_IPersistFile
et avec GCC: main.c:74: undefined reference to `IID_IPersistFile'
Bon après petite recherche dans les lib, il fallait linker avec uuid.lib ou libuuid.a (selon le compilo). Ce n'est pas le plus grave, j'aimerais juste savoir comment il se fait que j'aie du passer par la structure de l'interface pour compiler, aussi bien dans MSVC que MinGW ? J'ai compilé les deux en mode C "pur", et les exemples de la MSDN sont un coup avec l'interface "normale" et un coup avec l'utilisation de la structure interne, ce qui me laisse perplexe. Il y a aussi cette histoire de "&" devant les constantes IID_* :-/
Pour mon premier contact avec les interfaces, je trouve çà un peu chi*nt... Faut être obstiné, lol
19 déc. 2004 à 11:46
18 déc. 2004 à 13:51
Merci pour les commentaires.
AlexMAN > Je préfère céer mes boites de dialogues dynamiquement car je n'aime pas l'éditeur de ressources. Je préfère tout mettre dans le code tant que possible. Ca me permet de le mieux maitriser. Puisque j'utilise beaucoup les boites de dialogues, je trouve plus pratique de copier/coller la portion de création de la boite que d'être obligé d'ajouter à chaque fois une nouvelle ressource. Avec la méthode dynamique, on peut définir la position et les dimensions de la boite avant sa création. Ce ne sont que des exemples d'avantages car il y'en a d'autres comme la précision, la réutilisation du code, la portabilité pour les compilateurs Windows etc...
18 déc. 2004 à 11:19
J'ai pas encore regardé les codes mais déjà je te remercie beaucoup.
18 déc. 2004 à 09:15
D'abord merci pour ton prog, car c bien utile d'avoir un ptit programme comme ca !
Ensuite, j'ai une kestion :
Dans tous tes progs, tu crées des dialogs 'dynamikement', a partir de ton propre TEMPLATE, ya til une raison ou alors est ce que c juste une habitude ?
Voila, merci beaucoup
A bientot
+2(p-n)
18 déc. 2004 à 09:00
++
Nono.