begin process at 2010 03 22 14:29:31
  Trouver un code source :
 
dans
 
Accueil > Forum > 

C

 > 

Windows

 > 

Driver

 > 

Compilation driver windows


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

Compilation driver windows

mardi 10 avril 2007 à 14:16:35 | Compilation driver windows

BloP68

Bonjour,

Je suis actuellement en train de coder un driver, mais je me heurte a un probleme de compilation (je compile mes driver avec la commande build du DDK windows XP).
Il faut obligatoirement que je définnisse mes variable en début de chaque blocs. Pour mon code ca ne pose pas de probleme mais maintenant je doit faire appel a des API windows mais quand je lance la compile il me sort comme quoi il y a des erreurs dans les headers des librairie...:S
Est ce que quelqu'un pourrait m'aider s'il vous plait.

Merci d'avance.
mardi 10 avril 2007 à 14:27:26 | Re : Compilation driver windows

racpp

Administrateur CodeS-SourceS
Salut,
La programmation de drivers sous Windows se fait en Kernel-Mode. C'est un univers à part. De quelles APIs tu parles? Normalement les seules APIs accessibles directement en Kernel-Mode sont celles de ntoskernel.exe. Montre-nous les messages d'erreurs affichés par le compilateur.

mardi 10 avril 2007 à 14:38:45 | Re : Compilation driver windows

BloP68

Donc voila je souhaiterais utiliser dans mon driver des fonction windows permettant de gerer les Desktop (switch, ouvrir, fermer).
Merci pour ton aide.
Lorsque je lance la compilation je recois ces erreur(mais elle ne sont pas fonder car j'ai deja eu ce probleme avant d'inclure l'header "windows.h" dans mon code puis j'ai defini les variables en debut de bloc et plus de probleme :S) :

BUILD: Object root set to: ==> objchk
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: /i switch ignored
BUILD: Using 2 child processes
BUILD: Compile and Link for i386
BUILD: Loading C:\WINDDK\2600\build.dat...
BUILD: Computing Include file dependencies:
BUILD: Examining c:\winddk\rootkits\projet\test1 directory for files to compile.

    c:\winddk\rootkits\projet\test1 - 1 source files (179 lines)
BUILD: Compiling c:\winddk\rootkits\projet\test1 directory
1>Compiling - test1.c for i386
1>c:\winddk\2600\inc\crt\winuser.h(59) : error C2143: syntax error : missing ')'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(59) : error C2143: syntax error : missing '{'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(59) : error C2059: syntax error : ')'
1>c:\winddk\2600\inc\crt\winuser.h(63) : error C2143: syntax error : missing ')'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(63) : error C2143: syntax error : missing '{'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(63) : error C2059: syntax error : ')'
1>c:\winddk\2600\inc\crt\winuser.h(64) : error C2143: syntax error : missing ')'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(64) : error C2143: syntax error : missing '{'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(64) : error C2059: syntax error : ')'
1>c:\winddk\2600\inc\crt\winuser.h(65) : error C2143: syntax error : missing ')'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(65) : error C2143: syntax error : missing '{'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(65) : error C2059: syntax error : ')'
1>c:\winddk\2600\inc\crt\winuser.h(65) : error C2122: 'int' : prototype paramete
r in name list illegal
1>c:\winddk\2600\inc\crt\winuser.h(66) : error C2143: syntax error : missing ')'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(66) : error C2143: syntax error : missing '{'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(66) : error C2059: syntax error : ')'
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2143: syntax error : missing ')'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2143: syntax error : missing '{'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2059: syntax error : ')'
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2146: syntax error : missing ')'
 before identifier 'wParam'
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2144: syntax error : '<Unknown>'
 should be preceded by '<Unknown>'
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2144: syntax error : '<Unknown>'
 should be preceded by '<Unknown>'
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2143: syntax error : missing ')'
 before 'identifier'
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2081: 'WPARAM' : name in formal
parameter list illegal
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2061: syntax error : identifier
'wParam'
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2059: syntax error : ';'
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2059: syntax error : ','
1>c:\winddk\2600\inc\crt\winuser.h(67) : error C2059: syntax error : ')'
1>c:\winddk\2600\inc\crt\winuser.h(68) : error C2143: syntax error : missing ')'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(68) : error C2143: syntax error : missing '{'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(68) : error C2059: syntax error : ')'
1>c:\winddk\2600\inc\crt\winuser.h(70) : error C2143: syntax error : missing ')'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(70) : error C2143: syntax error : missing '{'
 before '*'
1>c:\winddk\2600\inc\crt\winuser.h(70) : error C2059: syntax error : ')'
(....)
1>c:\winddk\2600\inc\crt\winuser.h(216) : error C2061: syntax error : identifier
 'wvsprintfW'
1>c:\winddk\2600\inc\crt\winuser.h(216) : error C2059: syntax error : ';'
1>c:\winddk\2600\inc\crt\winuser.h(217) : error C2059: syntax error : 'type'
1>c:\winddk\2600\inc\crt\winuser.h(229) : error C2061: syntax error : identifier
 'wsprintfA'
1>c:\winddk\2600\inc\crt\winuser.h(229) : error C2059: syntax error : ';'
1>c:\winddk\2600\inc\crt\winuser.h(230) : error C2059: syntax error : 'type'
1>c:\winddk\2600\inc\crt\winuser.h(236) : error C2061: syntax error : identifier
 'wsprintfW'
1>c:\winddk\2600\inc\crt\winuser.h(236) : error C2059: syntax error : ';'
1>c:\winddk\2600\inc\crt\winuser.h(237) : error C2059: syntax error : 'type'
1>c:\winddk\2600\inc\crt\winuser.h(698) : error C2061: syntax error : identifier
 'HWND'
1>c:\winddk\2600\inc\crt\winuser.h(699) : error C2059: syntax error : '}'
1>c:\winddk\2600\inc\crt\winuser.h(706) : error C2061: syntax error : identifier
 'HWND'
1>c:\winddk\2600\inc\crt\winuser.h(706) : error C1003: error count exceeds 100;
stopping compilation
BUILD: Compile errors: not linking c:\winddk\rootkits\projet\test1 directory
BUILD: Done

    2 files compiled - 102 Errors

Merci pour ton aide.
mardi 10 avril 2007 à 15:10:36 | Re : Compilation driver windows

racpp

Administrateur CodeS-SourceS
Les fonctions de winuser.h ne sont pas faites pour être utilisées dans un driver. Elles sont réservées au User-Mode. Elles ne sont là que pour servir de prototypes en cas de besoin. On peut utiliser les APIs natives de ntdll.dll. Toutes les APIs User-Mode passent par celles de cette dll. Si tu peux montrer ton code ce sera plus facile.
Je repasserai ce soir pour voir.

mardi 10 avril 2007 à 17:53:07 | Re : Compilation driver windows

BloP68

Donc euh voila ca c'est une partie du code, le programme est un hook du clavier(il test si une touche est appeler puis apres il appelle ma fonction):(je sais qu'il y a moyen de faire des hook autrement que par un driver :D)

NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath )
{
    ...
    pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
    ...
}

NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
    ...  
    IoSetCompletionRoutine(pIrp, OnReadCompletion, pDeviceObject, TRUE, TRUE, TRUE);
    return IoCallDriver(((PDEVICE_EXTENSION) pDeviceObject->DeviceExtension)->pKeyboardDevice ,pIrp);
}

NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context)
{
    ...
    //si c'est la bonne touche on appelle la fonction
    SSwitch();
   
//sinon on passe
    ...
    if(pIrp->PendingReturned)
        IoMarkIrpPending(pIrp);
    return pIrp->IoStatus.Status;
}


VOID SSwitch()
{
    HWINSTA proc_ws;
    char desk_s[15];
    char desk_d[15];
    HDESK hdesk_s;
    HDESK hdesk_d;
   
    DbgPrint("Switch Deskstop");
    proc_ws = GetProcessWindowStation();
   
    if(Desk_S == 0) //si on est sur le bureau par defaut
    {
        sprintf(desk_s, "Bureau");
        hdesk_s = OpenDesktop(desk_s, DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL);
        SwitchDesktop(hdesk_s);
        CloseDesktop(hdesk_s);
        Desk_S == 1;
    }
    else if(Desk_S== 1) //si on est sur Bureau
    {
        sprintf(desk_d, "Default");
        hdesk_d= OpenDesktop(desk_d, DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL);
        SwitchDesktop(hdesk_d);
        CloseDesktop(hdesk_d);
    }
    else
        DbgPrint("Erreur dans le switch de desktop...Veuillez redemarrer le driver....");
}


Voila j'espere que ce morceau de code va pouvoir t'aider...
Je te remercie d'avance.
mercredi 11 avril 2007 à 02:52:32 | Re : Compilation driver windows

racpp

Administrateur CodeS-SourceS
Je parlais d'un code que je peux coller directement chez moi pour le tester et essayer de trouver les causes des erreurs.
mercredi 11 avril 2007 à 11:15:04 | Re : Compilation driver windows

BloP68

Désoler j'avais pas compris.

Alors voila je te dépose le code complet que tu puisse le compiler.

//MAKEFILE
#
# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
# file to this component.  This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#

!INCLUDE $(NTMAKEENV)\makefile.def

//SOURCES
TARGETNAME=TEST1
TARGETPATH=OBJ
TARGETTYPE=DRIVER
INCLUDES=..\..\inc
TARGETLIBS=$(DDK_LIB_PATH)\user32.lib
TARGETLIBS=$(DDK_LIB_PATH)\ndis.lib
SOURCES=test1.c

//test1.h
typedef struct _DEVICE_EXTENSION
{
    PDEVICE_OBJECT pKeyboardDevice; //pointer to next keyboard device on device stack
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;

//Fonction methode
NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp);
NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context);
NTSTATUS DispatchPassDown(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp);
VOID OnUnload( IN PDRIVER_OBJECT DriverObject );
VOID S_Switch();

//test1.c
#include "ntddk.h"
#include "ntddkbd.h"
#include "winuser.h"
#include "test1.h"

int numPendingIrps = 0;
BOOLEAN DeskS = 1;

VOID OnUnload( IN PDRIVER_OBJECT pDriverObject )
{
    PDEVICE_EXTENSION pKeyboardDeviceExtension;
    KTIMER kTimer;
    LARGE_INTEGER  timeout;
   
    DbgPrint("OnUnload");
    pKeyboardDeviceExtension = (PDEVICE_EXTENSION)pDriverObject->DeviceObject->DeviceExtension;
    IoDetachDevice(pKeyboardDeviceExtension->pKeyboardDevice);
    DbgPrint("Keyboard hook detached from device...\nWaiting tagged irp die");
    timeout.QuadPart = 1000000; //.1 s
    KeInitializeTimer(&kTimer);
   
    while(numPendingIrps > 0)
    {
        //Set the timer
        KeSetTimer(&kTimer,timeout,NULL);
        KeWaitForSingleObject(&kTimer,Executive,KernelMode,FALSE ,NULL);
    }
   
    IoDeleteDevice(pDriverObject->DeviceObject);
    DbgPrint("Tagged IRPs dead...Terminating...\n");
}

NTSTATUS DispatchPassDown(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
    DbgPrint("DispatchPassDown");
    IoSkipCurrentIrpStackLocation(pIrp);
    return IoCallDriver(((PDEVICE_EXTENSION) pDeviceObject->DeviceExtension)->pKeyboardDevice ,pIrp);
}

NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context)
{
    PDEVICE_EXTENSION pKeyboardDeviceExtension;
    int i;
    PKEYBOARD_INPUT_DATA keys;
    int numKeys;
   
    DbgPrint("OnReadCompletion");
    pKeyboardDeviceExtension = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;
   
    if(pIrp->IoStatus.Status == STATUS_SUCCESS)
    {
        keys = (PKEYBOARD_INPUT_DATA)pIrp->AssociatedIrp.SystemBuffer;
        numKeys = pIrp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);

        for(i = 0; i < numKeys; i++)
        {           
            if(keys[i].Flags == KEY_BREAK)
            {
                DbgPrint("%s\n","Key Up");
                if(keys[i].MakeCode == 0x38)
                {
                    DbgPrint("LAlt Release");
                    S_Switch();
                }
            }
        }
    }
    if(pIrp->PendingReturned)
        IoMarkIrpPending(pIrp);
    numPendingIrps--;
   
    return pIrp->IoStatus.Status;
}

NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
    PIO_STACK_LOCATION currentIrpStack;
    PIO_STACK_LOCATION nextIrpStack;
    DbgPrint("DispatchRead");
    currentIrpStack = IoGetCurrentIrpStackLocation(pIrp);
    nextIrpStack = IoGetNextIrpStackLocation(pIrp);
    *nextIrpStack = *currentIrpStack;
    IoSetCompletionRoutine(pIrp, OnReadCompletion, pDeviceObject, TRUE, TRUE, TRUE);
    numPendingIrps++;
   
    return IoCallDriver(((PDEVICE_EXTENSION) pDeviceObject->DeviceExtension)->pKeyboardDevice ,pIrp);
}


NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath )
{
    int i;
    PDEVICE_OBJECT pKeyboardDeviceObject;
    NTSTATUS status;
    PDEVICE_EXTENSION pKeyboardDeviceExtension;
    CCHAR ntNameBuffer[64] = "\\Device\\KeyboardClass0";
    STRING ntNameString;
    UNICODE_STRING uKeyboardDeviceName;
   
    DbgPrint("Driver Loaded");
    pDriverObject->DriverUnload = OnUnload;
   
    for( i = 0 ; i < IRP_MJ_MAXIMUM_FUNCTION; i++ )
        pDriverObject->MajorFunction[i] = DispatchPassDown;
   
    pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
   
    status = IoCreateDevice( pDriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_KEYBOARD, 0, TRUE, &pKeyboardDeviceObject);
    if(!NT_SUCCESS(status))
        return status;
   
    pKeyboardDeviceObject->Flags = pKeyboardDeviceObject->Flags | (DO_BUFFERED_IO | DO_POWER_PAGABLE);
    pKeyboardDeviceObject->Flags = pKeyboardDeviceObject->Flags & ~DO_DEVICE_INITIALIZING;
   
    RtlZeroMemory(pKeyboardDeviceObject->DeviceExtension, sizeof(DEVICE_EXTENSION));
   
    pKeyboardDeviceExtension = (PDEVICE_EXTENSION)pKeyboardDeviceObject->DeviceExtension;
   
    RtlInitAnsiString(&ntNameString, ntNameBuffer);
    RtlAnsiStringToUnicodeString(&uKeyboardDeviceName, &ntNameString, TRUE);
    IoAttachDevice(pKeyboardDeviceObject, &uKeyboardDeviceName, &pKeyboardDeviceExtension->pKeyboardDevice);
    RtlFreeUnicodeString(&uKeyboardDeviceName);
    DbgPrint("Clavier Hooker");
   
    return STATUS_SUCCESS;
}

VOID S_Switch()
{
    HWINSTA proc_ws;
    char desk_s[15];
    char desk_default[15];
    HDESK hdesk_s;
    HDESK hdesk_default;
   
    DbgPrint("Switch Deskstop");
    proc_ws = GetProcessWindowStation();
   
    if(DeskS == 0) //si on est sur le bureau par defaut
    {
        sprintf(desk_s, "desk");
        hdesk_s = OpenDesktop(desk_s, DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL);
        SwitchDesktop(hdesk_s);
        CloseDesktop(hdesk_s);
        desk_s = 1;
    }
    else if(DeskS == 1)
    {
        sprintf(desk_default, "Default");
        hdesk_default = OpenDesktop(desk_default, DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL);
        SwitchDesktop(hdesk_default);
        CloseDesktop(hdesk_default);
    }
    else
        DbgPrint("Erreur dans le switch de desktop...Veuillez redemarrer le driver....");
}
mercredi 11 avril 2007 à 20:24:35 | Re : Compilation driver windows

racpp

Administrateur CodeS-SourceS
Salut,
Je viens de tester ton code chez moi. J'ai exactement les mêmes erreurs. Il parait que winuser.h n'est pas fait pour être inclus dans un projet en kernel-mode. Ou bien il faudra une sorte de #define pour pouvoir l'inclure. Toutes les erreurs signalées par le compilateur se trouvent dans winuser.h alors qu'il est parfaitement correct.
Personnellement, pour travailler en kernel-mode je ne fais appel qu'aux fonctions et aux services fournis par le système. Je remplacerai les APIs utilisées dans ta fonction S_Swith() par les services correspondant du système:
NtUserGetProcessWindowStation()
NtUserOpenDesktop()
NtUserSwitchDesktop()
NtUserCloseDesktop()
Je viens de voir que ce sont des services implémentés dans w32k.sys et accessibles depuis la table des services système (SSDT) et donc accessibles si on connait leurs IDs. Malheureusement, ils ne sont pas documentés. Leurs IDs peuvent changer selon la version Windows et même selon le service pack. En cherchant un peu sur le net, et avec quelques tests, tu finiras par résoudre ce problème. Je ne peux pas tester pour toi car il y'a risque d'avoir de nombreux plantages et redémarrage du PC.
Il faudra donc virer winuser.h de tes incldes. HWINSTA et HDESK sont des simples HANDLES qui sont en réalités des PVOIDs.
J'essaierai plutard de te trouver les prototypes des services listés plus haut.



mercredi 11 avril 2007 à 20:47:56 | Re : Compilation driver windows

BloP68

Oakay ca marche je vais regarder..ca...Je te remerci de ton aide. J'avais aussi essayer de chercher des fcontion similaire en mode kernel mais j'avais pas trouver mais maintenant que tu les as trouver un tour de google et je devrais peux être trouver...:D

Merci.
mercredi 11 avril 2007 à 21:51:45 | Re : Compilation driver windows

BloP68

Tien je vien de trouver la liste des syscall des fonctions.
http://inside.iatp.org.ua/Calllist.html
Est ce que tu pourrais juste m'expliquer comment les utiliser. Car les drivers windows c'est deja a la limite de mes connaissance mais alors là je commence à être completement perdu j'ai très envie d'apprendre mais dès qu'on pousse un peux dans des sujet complex on trouve plus beaucoup de documentation sur internet alors si tu aurais des sources des liens. Et si deja pour commencer tu pouvais me dire comment utiliser les syscall pour que je puisse tenter de finir la 1ere version de mon prog que je puisse ensuite continuer a apprendre tout ca. Je te remercie d'avance.

1 2

Cette discussion est classée dans : windows, probleme, compilation, compile, driver


Répondre à ce message

Sujets en rapport avec ce message

Enorme probleme lors de la compilation avec Visual C++ 6 [ par hepho ] Alors mon probleme est le suivantlorsque que je desire compiler mon programme une erreur apparaitLe pilote de clavier specifie par la ligne KEYBOARD = probleme de compilation [ par lesaixol ] Bonjour,je travaille sous Visual C++ et windows NT et lorsque je compile un projet sous mon compte utilisateur, j'obtiens un executable dont la taille probleme de compilation dans dev C++ [ par lypsik ] Bonjour,Recement je me suis remis a la programmation et j utilise pour compiler soit dev C++ , soit visual C++.Le probleme quand je compile dans DEv C vc2005 dll [ par lilington ] Bonjourvoila je viens d'installer msvc2005 le probleme c'est que je ne peux pas executer mes prog.je recois un message windows disant que la dll:msvcr probleme compilation [ par Kelm0 ] Bonjour, j'ai dev c++, et j'ai fais 2 classes avec 1 fichier par classe + le main.Le compilateur me lance un message d'erreur : multiple definition of [HP] Driver Audio [ par cpp26 ] salut;j'ai un notebook HP 2510p.Depuis quelques jours je l'ai formaté.En effet j'avais pas du probleme avec les drivers ;je les ai trouvés  au site of windows rencontre un probleme [ par parain74 ] Bonjour, j'ai écrit un programme en c via labwindows, lorsque je lance mon programme, de temps en temps windows me met le fameux message "windows a re subsystem console et windows [ par draluorg ] Salut a tous,J'ai une appli windows a laquelle j'aimerais bien mettre la possibilite d'etre executer en ligne de commande avec des parametres.Le probl probleme de compilation sous ubuntu [ par cellfisher ] Bonjour,a tous je debute dans l'univert de *nix et aussi dans le language "c".Mais j ai quelques problems de compilations Exemple = "fseek.c:7: attent


Nos sponsors


Appels d'offres

Sondage...

Comparez les prix

CalendriCode

Mars 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,593 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales