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...
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.