2012-06-11 1 views
4

Je cherche l'exemple du pilote de filtre de système de fichiers dans le WDK appelé minispy ... spécialement la façon dont ils passent des données entre l'espace utilisateur et le noyau en utilisant les fonctions FilterSendMessage et connexes:Pilote Windows - Passer des chaînes entre le mode utilisateur et le mode noyau. Dynamiquement taille struct

http://msdn.microsoft.com/en-us/library/windows/hardware/ff541513%28v=vs.85%29.aspx

le code que je regarde et se référer à devrait être situé ici si vous installez le WDK:

winddk racine Dir \ Version \ src \ filesys \ MiniFilter \ minispy

donc, fondamentalement, la première chose que je suis à la recherche une t est le fichier d'en-tête partagé inc \ minispy.h:

#pragma warning(push) 
#pragma warning(disable:4200) // disable warnings for structures with zero length arrays. 

typedef struct _LOG_RECORD { 


ULONG Length;   // Length of log record. This Does not include 
ULONG SequenceNumber; // space used by other members of RECORD_LIST 

ULONG RecordType;  // The type of log record this is. 
ULONG Reserved;   // For alignment on IA64 

RECORD_DATA Data; 
WCHAR Name[];   // This is a null terminated string 

} LOG_RECORD, *PLOG_RECORD; 

Ici, nous avons Nom qui est pas donné une taille explicite et on dirait qu'ils utilisent quelques options pour désactiver les avertissements pour cela.

Maintenant, je regarde où cela est rempli, le filtre \ mspyLib.c:

(je sens que je fait que copier étaient pertinentes ... pensé)

VOID SpySetRecordName (__inout PLOG_RECORD LogRecord, __in PUNICODE_STRING Name) 

    ULONG nameCopyLength; 
    PCHAR copyPointer = (PCHAR)LogRecord->Name; 
    ... 
    // A bunch of code for getting nameCopyLength from UNICODE_STRING -- I understand this. 
    ... 

    // comment about adding sizeof(PVOID) for IA64 alignment -- I understand this. 
    LogRecord->Length = ROUND_TO_SIZE((LogRecord->Length + nameCopyLength + sizeof(UNICODE_NULL)), sizeof(PVOID)); 

    RtlCopyMemory(copyPointer, Name->Buffer, nameCopyLength); 

    copyPointer += nameCopyLength; 

    *((PWCHAR) copyPointer) = UNICODE_NULL; 

Ma question est essentiellement est-ce la meilleure méthode pour passer des chaînes à l'intérieur d'une structure pour la communication utilisateur-noyau en utilisant FilterSendMessage? J'ai du mal à imaginer la disposition de ces structures et ce qui se passe si la chaîne de nom s'avère trop grande. En outre, l'allocation pour la structure se produit dans le composant de l'espace utilisateur sur sa pile mais le redimensionnement se produit dans le composant de l'espace noyau agissant sur un pointeur passé vers la structure. Je pense que c'est plus un problème de moi ne comprenant pas des tableaux de longueur zéro mais comment le composant d'espace utilisateur sait combien d'espace à réserver pour le champ de nom avant qu'il soit redimensionné?

Ce essentiellement semble être une forme de tableaux de taille dynamique qui est discuté dans plusieurs sujets tels que:

C: Recommended style for dynamically sized structs

+0

Ok ... Je pense que je comprends cela. Ils semblent allouer un tampon générique d'une taille spécifique du côté de l'espace utilisateur et ensuite séparer le tampon qui est retransmis dans les structures LOG_RECORD en fonction de la taille de chacun ... Cela a du sens maintenant. – mcot

Répondre

0

Tout d'abord, oui, il semble être une forme de tableau de taille dynamique. Fondamentalement, la chaîne Name est placée juste après la fin de la structure. Lors du passage des données entre l'utilisateur et le noyau, il est très souvent utilisé comme un truc. Cette approche présente plusieurs avantages:

  • Il ne nécessite pas plusieurs allocations de mémoire.
  • Lorsque vous passez des données du mode utilisateur au mode noyau (et inversement), vous devez souvent copier la mémoire d'un tampon vers un autre (je crois que FilterSendMessage le fait). Si nous utilisons un pointeur vers un emplacement mémoire différent pour stocker la chaîne, nous aurons besoin de plusieurs appels pour copier (ou verrouiller) la mémoire. Lorsque vous manipulez des messages fournis par l'utilisateur, il est impossible de connaître la structure de votre structure de données. La clé pour résoudre ce problème est d'utiliser une structure simple comme celle décrite ci-dessus.

C'est une approche très utile. Personnellement, j'utilise cette astuce pour éviter les appels multiples aux fonctions de mémoire (allouer, copier, déplacer, etc.) même dans des applications simples. Lors du développement de pilotes Windows je vois ces structures partout (à savoir ZwQueryInformationFile, ZwQueryDirectoryFile etc.)

+0

Avez-vous déjà envisagé d'utiliser des MDL pour éviter de telles copies? En outre, il est très probable que le gestionnaire de filtres utilise exactement cette approche pour passer le "message" en mode utilisateur. – 0xC0000022L

Questions connexes