9
votes

Comment puis-je convertir un chemin de chemin natif (NT) en un nom de chemin Win32?

Je travaille sur la signalisation de certaines informations glanées à partir d'API du système natif. (Je sais que c'est mauvais ... Mais je reçois des informations que je ne peux pas obtenir autrement, et j'ai peu de problème avec qui devoir mettre à jour mon application si / quand ce temps vient autour.)

L'API Native Renvoie des chemins maternels natifs, comme on le voit par ob , c'est-à-dire \ \ systemroot \ system32 \ ntoskrnl.exe ou \ ?? \ c: \ fichiers de programme \ VMware Workstation \ vstor-ws60.sys .

Je peux remplacer les préfixes courants, c'est-à-dire xxx

mais je serais fortement surpris s'il n'y a pas d'autre API, natif ou autre, qui les convertira dans des noms de chemin Win32. Un tel API existe-t-il?


17 commentaires

La fonction d'API Shell PATHCANONICALISEZ-t-elle Faites-vous le tour? msdn.microsoft.com/en-us/ Bibliothèque / BB773569% 28V = VS.85% 29.aspx


@PRAETORIAN: Non, Pathcanonicalize accepte les chemins Win32. J'essaie d'obtenir un chemin Win32.


Je ne connais aucune fonction de ce type, et il n'est pas toujours possible: NT peut utiliser des chemins qui Win32 ne peuvent pas du tout. Bonne chance de toute façon ...


@Billy: Voici quelque chose que vous pourriez essayer. Première utilisation ntcreatefile ( msdn.microsoft.com/en-us/library/bb432380%28v=vs.85%29.aspx ) Pour ouvrir le fichier, le volume, etc. pour la lecture. Ensuite, utilisez la poignée retournée pour obtenir le chemin complet comme décrit ici ici msdn.microsoft.com/en-us/library/aa366789%28v=vs.85%29.aspx


@Efement: True, mais NT doit le faire quelque part. Après tout, NTqueryDirectoryFile renvoie des sentiers maternels et Findfirstfile renvoie Win32 chemins ...


Ne semble pas définitif pour moi. Bien sûr, FindFirstFile peut facilement construire des chemins Win32; Vous devez lui donner un pour commencer, contrairement à zwquerydirectoryfile qui prend une poignée à la place. Bien sûr, votre problème serait résolu s'il y avait une API pour renvoyer un chemin Win32 d'une poignée.


Si vous recherchez, vous pouvez trouver Obtention d'un nom de fichier à partir d'une poignée de fichier Sur MSDN, mais cela renvoie toujours un chemin NT et seulement fonctionne pour des objets pouvant être mappés en mémoire.


@EphemIent: Si je peux ouvrir la poignée réelle, je pouvais simplement appeler getfileinformationbyhandleex ... Je préfère éviter d'éviter d'ouvrir la poignée au fichier réel si possible.


@Billy: Toutes les poignées de fichier ouverte ne sont pas créées égales. Si vous ouvrez pour Query_Information niveau d'accès (et non generic_read ou generic_write ), vous ne devez interférer en aucun cas avec d'autres programmes à l'aide du fichier .


@Ben: Bien que vrai, cela nécessite toujours d'avoir accès au fichier, ce que je n'ai peut-être pas.


Plutôt intéressant. La dernière fois que j'ai programmé pour Windows, je suis sûr que GetFileInformationbyHandleex n'existait pas encore. Je conviens que Open + Query n'est pas un moyen agréable de le faire (bien que la requête Open + MMAP + est pire), mais il semble qu'il n'y ait aucune méthode publiquement exposée à cela.


@Efement: Ah - on dirait qu'il a été ajouté à Vista. Peu importe. On peut appeler ntqueryfileinformation et le demander pour file_names_information à partir d'une poignée.


@PRAETORIAN: Mettez cela dans une réponse afin que nous puissions la remettre.


@Billy: C'est volontiers que vous pourriez même avoir l'honneur de frapper mon représentant sur 1k :-)


D'où vient GetWindowsPath ()? Pourquoi ne pas utiliser rtldospathnameontPathName_u_withstatus?


@Norbertboros Je n'arrive pas à trouver de la documentation sur une fonction de ce nom.


@Billyonéal je sais ... Il y a tellement de sans papiers, mais existent et utilisé depuis XP à 10 :) Je posterai un gist ou quelque chose avec certaines de ces fonctions et explications.


6 Réponses :


2
votes

1 commentaires

+1 - Ceci est intéressant, mais il s'agit de transformer un chemin Win32 dans un autre type de chemin Win32. Je n'ai pas de chemin Win32 en premier lieu. Les fonctions PathXXX ne vont pas travailler sur ce que j'ai.



8
votes

Nous faisons cela dans le code de production. Autant que je sache, il n'y a pas d'API (public ou privé) qui gère cela. Nous faisons juste des comparaisons de cordes avec quelques préfixes et cela fonctionne pour nous.

Apparemment, il existe une fonction nommée rtlntpathnametodospathName () dans ntdll.dll (introduite avec XP?), mais je n'ai aucune idée de ce qu'il fait; Je suppose que cela a plus à voir avec des trucs comme \ Appareil \ HardDisk0, cependant.

Je ne suis pas sûr qu'il y ait vraiment besoin d'une telle fonction, cependant. Win32 passe des chemins (au sens de Createfile, etc.) à NT; NT ne passe pas les chemins pour Win32. Donc, ntdll.dll n'a pas vraiment besoin d'aller des chemins NT à Win32 Chemins. Dans le cas rare où la fonction de requête NT renvoie un chemin complet, toute fonction de conversion pourrait être interne à la DLL Win32 (par exemple non exportée). Je ne sais même pas s'ils se déroulent, comme des trucs comme getModuleFilename () reviendront tout ce que le chemin a été utilisé pour charger l'image. Je suppose que c'est juste une abstraction fuite.


3 commentaires

Plutôt. Les seules que j'ai vues sur une base régulière sont \\\ ??? \\ et \\ Systemroot, et même à ce moment-là assez rares (typiquement avec des processus de bas niveau lancés au début de la séquence de démarrage. Parfois parfois dans le registre, généralement liée auxdits processus.


Je suis en train de bouleverser avec des trucs sans papiers et tous ces préfixes semblent être courants ici. Je suppose qu'il y a une raison qu'ils sont sans papiers: p


Il est dommage que Microsoft ne fournisse pas d'API documenté pour cela. En interne, Windows convertit les chemins NT vers un chemin DOS toute la journée, mais nous les programmeurs ne le peuvent pas. Si vous êtes intéressé à utiliser comment utiliser rtlntpathnametodoName () consultez ici: forum.sysinternals.com/... < / a>



5
votes

Voici quelque chose que vous pourriez essayer. Première utilisation NTCreatefile pour ouvrir le fichier , volume, etc. pour la lecture. Ensuite, utilisez la poignée renvoyée pour obtenir le chemin complet comme décrit Ici .


2 commentaires

+1 :) Notez que l'on peut probablement ignorer l'étape de mappage de fichier en appelant ntqueryfileinformation et demandant la classe d'informations FileNameInformation . (Bien que je n'ai pas encore testé cela, et bien sûr, ça va dans les trucs sans papiers ...)


GetFinalPathNameByhandle pourrait aider à nettoyer ce problème!



2
votes

9 commentaires

Cela fonctionne - mais le problème est que vous avez besoin d'accéder à l'emplacement du fichier afin de l'exécuter (car vous devez pouvoir ouvrir une poignée) - je n'ai souvent pas cela.


@Billy: Tout ce dont vous avez besoin est File_Read_ATtributes Accès, que vous pouvez presque toujours obtenir. Si vous ne pouvez pas l'obtenir, essayez-le sur le répertoire parent, puis concaténez le nom du fichier à la fin. (Vous ne pouvez pas convertir sans aucune poignée, car ce n'est pas toujours un mappage unique.)


@Mehrdad: Il doit être possible de convertir sans poignée. FindFirstFile / FindNextFile / FindClose Ne pas ouvrir les poignées. Vous pouvez les utiliser pour répertorier une structure de répertoire même si vous ne pouvez lire aucun attribut sur le fichier. Cette solution fonctionne, donc +1, mais cela ne m'aide vraiment pas :(


@Billy: En fait, FindFirstFile fait ouvre une poignée dans le répertoire! Qu'est-ce qui te fait penser que ça ne va pas? :)


@Mehrdad: le répertoire, oui. Pas les fichiers dans le répertoire.


@Billy: Mais comme je l'ai mentionné dans mon commentaire, vous ne pouvez pas simplement essayer ma méthode sur le répertoire parent et concaténer les noms de fichiers à la fin? On dirait que cela fonctionnerait.


@Mehrdad: Cela se transforme simplement sur un autre labyrinthe de manipulations de cordes. Cela ne fonctionnera pas de la boîte, par exemple, avec \ ?? \ \ c: \ windows \ .. . Stripping Le dernier fichier conduit à C: \ Windows, à la fin de la .. Remettez en avant C: \ Windows \ ... Je suppose que vous pourriez ré-canoniser ensuite ... de toute façon, la série actuelle de manipulations de cordes n'a pas encore manipulé.


@Billy: Huh, d'accord ... si vous rencontrez des problèmes avec votre méthode actuelle, je suppose que cela a essayé d'essayer. :)


GetFinalPathNameByhandle est le meilleur moyen d'aller, de loin. Vous n'avez pas besoin de savoir si la cible est un fichier ou un répertoire, il suffit d'utiliser créefilew pour obtenir une poignée pour votre chemin, passant 0 (zéro) pour dwedesireAccess ( fichier_access ) et file_flag_backup_semantiques (uniquement). Ceux-ci indiquent CreateFilew que vous n'observez pas le fichier, ce qui contourne les problèmes de sécurité certaines personnes mentionnées. Vous serez toujours en mesure d'utiliser getfindalpathNamebyhandle pour résoudre un chemin complet et minimal de la cible. Je fais cela fortement et avec succès pour résoudre les points répartis sur le volume croisé toute la journée.




4
votes

Ceci est un peu en retard, mais je posterai toujours ma réponse depuis même aujourd'hui c'est une très bonne question!

Je partagerai l'une de mes fonctions testées et utilisées pour la conversion de NT vers DOS. Dans mon cas, j'ai aussi dû convertir d'ANSI en Unicode, il s'agit donc d'un petit bonus pour que vous puissiez voir et comprendre comment cela peut être fait. P>

Tout ce code peut être utilisé en mode utilisateur, donc nous Besoin de préparer d'abord certaines choses. P>

Définitions & Structures: strong> p>

UNICODE_STRING us;
UNICODE_STRING DosPath;
ANSI_STRING as;

as.Buffer = (char*)malloc(strlen(NT_PATH_FILE_OR_DIR) + 1);
strcpy(as.Buffer, NT_PATH_FILE_OR_DIR);
as.Length = as.MaximumLength = us.MaximumLength = us.Length = strlen(NT_PATH_FILE_OR_DIR);

MyRtlAnsiStringToUnicodeString(&us, &as, TRUE);

NtPathNameToDosPathName(&DosPath, &us);


0 commentaires