[.net2] stocker et lire une donnée utilisateur dans l'espace de données privées d'une fenêtre

Soyez le premier à donner votre avis sur cette source.

Vue 6 781 fois - Téléchargée 349 fois

Description

C'est en regardant un webcast des Mercredi du Développement sur la sécurité pour les développeurs qui m'a décidé à fournir cet exemple.
Exemple sous forme d'une classe offrant la possibilité d'accéder en lecture/écriture à une donnée utilisateur se situant dans l'espace privées des fenêtres.

Ceci grâce à GetWindowLongPtr/SetWindowLongPtr. Ces 2 fonctions permettent de d'accéder aux informations d'une fenêtre, notamment à l'espace réservé à une donnée utilisateur (flag GWLP_USERDATA).

Type des données supportées en lecture/écriture:
String/Bool/Byte/Short/Ushort/Int/UInt/Float/Long/ULong/Double/Decimal/DateTime/IntPtr

Source MSDN:
GetWindowLongPtr: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windowclasses/windowclassreference/windowclassfunctions/getwindowlongptr.asp
SetWindowLongPtr: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windowclasses/windowclassreference/windowclassfunctions/setwindowlongptr.asp

Source / Exemple :


/// <summary>
        /// Lit les données privées utilisateur de type chaine de caractères.
        /// </summary>
        /// <param name="hWnd">Handle d'une fenêtres</param>
        /// <param name="ReturnedValue">Chaine de caractères récupérée.</param>
        public static void GetPrivateStringUserData(IntPtr hWnd, out string ReturnedValue)
        {
            if (hWnd != IntPtr.Zero)
            {
                //Obtient un pointeur vers l'espace de données utilisateur privée.
                IntPtr pRet = NativeMethods.GetWindowLongPtr(hWnd, GWLP_USERDATA);

                if (pRet != null)
                {
                    //Lecture de la chaine pointée par pRet.
                    string szRet = Marshal.PtrToStringAuto(pRet);
                    ReturnedValue = szRet;
                }
            }
            else
                ReturnedValue = string.Empty;
        }

        /// <summary>
        /// Lit les données privées utilisateur de type DateTime.
        /// </summary>
        /// <param name="hWnd">Handle d'une fenêtres</param>
        /// <param name="ReturnedValue">Valeur DateTime récupérée.</param>
        public static void GetPrivateDateTimeUserData(IntPtr hWnd, out DateTime ReturnedValue)
        {
            if (hWnd != IntPtr.Zero)
            {
                IntPtr pRet = NativeMethods.GetWindowLongPtr(hWnd, GWLP_USERDATA);

                if (pRet != null)
                {
                    long lRet = Marshal.ReadInt64(pRet);

                    DateTime dtRet = DateTime.FromBinary(lRet);

                    ReturnedValue = dtRet;
                }
            }
            else
                ReturnedValue = new DateTime();
        }

        /// <summary>
        /// Ecrit une donnée de type chaine de caractères.
        /// </summary>
        /// <param name="hWnd">Handle d'une fenêtres</param>
        /// <param name="data">Chaine de caractères à écrire.</param>
        public static void SetPrivateUserData(IntPtr hWnd, string data)
        {
            if (hWnd != IntPtr.Zero && !string.IsNullOrEmpty(data))
            {
                //Alloue un handle dans l'espace mémoire non managée pour notre chaine data.
                GCHandle gch = GCHandle.Alloc(data, GCHandleType.Pinned);
                IntPtr pObj = gch.AddrOfPinnedObject();

                //Ecrit la chaine dans l'espace de données utilisateur privée.
                NativeMethods.SetWindowLongPtr(hWnd, GWLP_USERDATA, pObj);

                gch.Free();
            }
        }

        /// <summary>
        /// Ecrit une donnée de type DateTime.
        /// </summary>
        /// <param name="hWnd">Handle d'une fenêtres</param>
        /// <param name="data">Valeur DateTime à écrire.</param>
        public static void SetPrivateUserData(IntPtr hWnd, DateTime data)
        {
            if (hWnd != IntPtr.Zero)
            {
                long lData = data.ToBinary();

                GCHandle gch = GCHandle.Alloc(lData, GCHandleType.Pinned);
                IntPtr pObj = gch.AddrOfPinnedObject();

                NativeMethods.SetWindowLongPtr(hWnd, GWLP_USERDATA, pObj);

                gch.Free();
            }
        }

Conclusion :


Voila voila j'espère vous avoir fait découvrir cet espace utilisateur assez méconnue sur les fenêtres. Pour ma part je ne connaissais pas !
Bien entendu notes, commentaires sont les bienvenues
Bon dév...

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
81
Date d'inscription
lundi 26 septembre 2005
Statut
Membre
Dernière intervention
22 octobre 2008

J'ai pas encore trouver a quoi cela peut servir concrêtement, mais peut-être dans un cas particulier ?
Messages postés
302
Date d'inscription
samedi 22 octobre 2005
Statut
Membre
Dernière intervention
2 novembre 2008
4
Quelqu'un a un exemple de situation ou cette méthode pourrait être utile ?
Messages postés
2375
Date d'inscription
jeudi 12 juillet 2001
Statut
Modérateur
Dernière intervention
15 décembre 2018
22
Sa dépend de quel côté on se place :)
Messages postés
302
Date d'inscription
samedi 22 octobre 2005
Statut
Membre
Dernière intervention
2 novembre 2008
4
>>> n'importe qui connaissant le handle de n'importe quelles fenêtres peut accéder à cette donnée.

Ca peut être un avantage.
Ne connaissant pas cette méthode je me demandais pourquoi vouloir l'implémenter
Messages postés
2375
Date d'inscription
jeudi 12 juillet 2001
Statut
Modérateur
Dernière intervention
15 décembre 2018
22
Qui a parlé d'un avantage ? (déconseillé si donnée sensible)
C'est clair que je doute que beaucoup de dév (hors chez MS) se servent de cet espace utilisateur pour y stocker une donnée mais faut savoir que cet espace existe et que n'importe qui connaissant le handle de n'importe quelles fenêtres peut accéder à cette donnée.

C'est juste une démo à but pédagogique pour manipuler la donnée de cet espace utilisateur.

++
Afficher les 6 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.