« L’application n’arrive pas à lire au démarrage la clé de licence que l’installeur a pourtant écrite. Et dans regedit, la valeur est bien là. » — voilà le type de signalement que nous avons reçu en accompagnant la migration 64 bits d’un logiciel de liaison avec des équipements. En creusant, la valeur se trouvait sous HKLM\Software\Wow6432Node\NomDeLaSociété. L’application, reconstruite en 64 bits, allait lire HKLM\Software\NomDeLaSociété, où il n’y avait rien : voilà la chute de l’histoire.
Ce genre de « la valeur que j’ai écrite n’est plus là » ou « elle est visible dans regedit mais invisible depuis l’application » reste un mystère, même après une vérification visuelle minutieuse, tant qu’on ignore deux mécanismes. Le premier, c’est que sur Windows 64 bits, le registre se présente à un endroit différent selon la bitness du processus (la distinction entre un processus qui s’exécute en 32 bits ou en 64 bits) — il s’agit de la redirection de registre opérée par WOW64 (Windows 32-bit on Windows 64-bit, le sous-système qui permet à Windows 64 bits d’exécuter des applications 32 bits). Le second, c’est qu’une écriture faite avec des droits insuffisants est silencieusement transférée ailleurs — c’est la virtualisation de registre UAC. Comme les deux « réussissent sans erreur », le problème n’apparaît qu’au moment où l’endroit où l’on a écrit et celui où l’on lit divergent, c’est-à-dire typiquement lors d’une migration 64 bits ou d’un changement d’installeur.
Cet article s’adresse aux développeurs d’applications métier Windows. Il détaille, avec des sources officielles à l’appui, le mécanisme de la redirection de registre WOW64 et l’inventaire des clés redirigées ou partagées, les conditions de déclenchement de la virtualisation de registre UAC, les dégâts concrets qui surviennent côté installeur et enregistrement COM, et enfin la bonne façon d’expliciter la vue en C#, en C++ et avec reg.exe.
1. La conclusion, d’abord
- Le registre de Windows 64 bits possède deux vues, une vue 64 bits et une vue 32 bits, et l’accès d’un processus 32 bits à
HKLM\Softwareest transparemment redirigé par le redirecteur de registre vers l’emplacement physiqueHKLM\Software\Wow6432Node. L’application ne voit ni erreur ni avertissement.1 - L’emplacement physique Wow6432Node est une zone réservée du système. N’y accédez jamais directement en codant le chemin en dur (sur Windows 10 on ARM, un autre emplacement,
WowAA32Node, est utilisé pour les applications ARM 32 bits). Pour accéder à une autre vue, utilisez les moyens officiels (les indicateurs ou RegistryView décrits plus loin).12 - Seule une partie des clés est redirigée ; d’autres sont partagées. À partir de Windows 7,
HKLM\SOFTWAREest « redirigée »,HKLM\SOFTWARE\Classesest « partagée », mais en dessous,CLSIDetInterfaceredeviennent « redirigées » — une structure imbriquée.3 - Pour accéder à une autre vue : en Win32, indiquez
KEY_WOW64_64KEY/KEY_WOW64_32KEYdans lesamDesireddeRegOpenKeyExet consorts ; en .NET, indiquezRegistryView.Registry64/Registry32àRegistryKey.OpenBaseKey; en ligne de commande, utilisez/reg:64//reg:32avecreg.exe.245 - Lorsqu’un processus interactif 32 bits sans droits administrateur écrit dans
HKLM\Software, la virtualisation de registre UAC peut transférer cette écriture versHKEY_USERS\<SID>_Classes\VirtualStore\Machine\Software. L’écriture « réussit », et le piège est que l’auteur lui-même, en relisant, la voit dans une vue fusionnée.6 - Indiquer
requestedExecutionLeveldans le manifeste désactive la virtualisation des fichiers et du registre. Autrement dit, seuls les anciens EXE sans manifeste sont concernés par la virtualisation.7 - La virtualisation de registre est une technologie de compatibilité provisoire, et Microsoft indique clairement son intention de la supprimer dans une future version de Windows. N’y comptez pas dans une nouvelle application : la bonne conception consiste à « ne pas écrire dans HKLM ».6
- L’enregistrement CLSID de COM (
HKCR\CLSID=HKLM\Software\Classes\CLSID) est séparé par bitness. L’enregistrement d’un serveur COM 32 bits est invisible depuis un client 64 bits, ce qui est une cause classique de « Classe non enregistrée (0x80040154) ».3
Vue d’ensemble des deux mécanismes
Les deux mécanismes traités dans cet article diffèrent par qui, quoi, et vers où le transfert a lieu. La redirection relève de la « bitness » et s’applique à la fois à la lecture et à l’écriture ; la virtualisation relève des « droits » et ne s’applique qu’à l’écriture. Comme les deux se confondent facilement, voici une vue d’ensemble en un schéma avant d’entrer dans le détail.
flowchart TD
S["Un processus manipule la sous-arborescence Software de HKLM"] --> B{"Le processus est-il en 32 bits ?"}
B -- "32 bits" --> R["Redirection de registre WOW64<br/>Une question de bitness, s'applique à la lecture et à l'écriture"]
B -- "64 bits" --> N["Pas de redirection<br/>Lit et écrit directement dans HKLM Software"]
R --> RV["La lecture/écriture se fait en réalité<br/>sous Wow6432Node = vue 32 bits"]
RV --> W{"Pour une écriture, le processus a-t-il<br/>le droit d'écrire dans cette clé ?"}
N --> W
W -- "Processus interactif 32 bits sans manifeste" --> V["Virtualisation de registre UAC<br/>Une question de droits, s'applique uniquement à l'écriture"]
V --> VS["Transfert vers le VirtualStore propre à l'utilisateur<br/>La lecture renvoie une vue fusionnée avec l'emplacement d'origine"]
W -- "Processus 64 bits, service ou manifeste présent" --> E["Échec net par refus d'accès"]
La branche de gauche de ce schéma (qui est en 32 bits) correspond aux chapitres 2 et 3 ; la branche en bas à droite (droits et manifeste) correspond au chapitre 5.
2. La redirection de registre WOW64 — où regarde un processus 32 bits ?
Windows 64 bits exécute les applications 32 bits sur un sous-système appelé WOW64. Le redirecteur de registre présente alors des vues logiques distinctes aux processus 32 bits et 64 bits. Les deux appellent la même API avec le même nom de clé (HKEY_LOCAL_MACHINE\Software\...), mais l’emplacement physique réellement lu ou écrit diffère : c’est là le cœur du mécanisme.1
L’emplacement physique des clés redirigées est Wow6432Node. Par exemple, HKEY_LOCAL_MACHINE\Software vu par un processus 32 bits correspond physiquement à HKEY_LOCAL_MACHINE\Software\Wow6432Node. Cette correspondance est totalement transparente pour l’application : celle-ci peut manipuler le registre en croyant s’exécuter sur un Windows 32 bits.1
Voici, sous forme de tableau, qui regarde quoi.
| Source d’accès | Chemin indiqué dans le code | Emplacement physique réellement lu/écrit |
|---|---|---|
| Processus 64 bits | HKLM\Software\MyApp |
HKLM\Software\MyApp |
| Processus 32 bits | HKLM\Software\MyApp |
HKLM\Software\Wow6432Node\MyApp |
Processus 32 bits + KEY_WOW64_64KEY (RegistryView.Registry64) |
HKLM\Software\MyApp |
HKLM\Software\MyApp |
Processus 64 bits + KEY_WOW64_32KEY (RegistryView.Registry32) |
HKLM\Software\MyApp |
HKLM\Software\Wow6432Node\MyApp |
| Écriture par un processus interactif 32 bits, droits standard, sans manifeste | HKLM\Software\MyApp |
HKCU\Software\Classes\VirtualStore\Machine\Software\Wow6432Node\MyApp (virtualisation après redirection WOW64 ; voir chapitre 5) |
| regedit (processus 64 bits) | — | Affichage basé sur la vue 64 bits. Wow6432Node reste visible en tant que clé physique |
L’anecdote du début n’est rien d’autre que ce tableau. La valeur écrite par l’installeur 32 bits se trouve physiquement sous Wow6432Node, tandis que l’application recompilée en 64 bits lit directement HKLM\Software. Comme regedit voit les deux, le témoignage de terrain « elle est bien là dans regedit » et le constat « elle est invisible depuis l’application » coexistent sans contradiction.
On est tenté, à ce stade, de coder en dur le chemin Wow6432Node pour faire coller les choses, mais c’est un anti-pattern explicitement proscrit par la documentation officielle. L’emplacement physique de la redirection appartient au système et peut changer. Sur Windows 10 on ARM, par exemple, l’emplacement de redirection des applications ARM 32 bits est une clé différente, WowAA32Node.12 Si vous voulez lire une autre vue, utilisez les moyens officiels du chapitre 4.
Détail technique : WOW64 corrige aussi les chaînes REG_SZ/REG_EXPAND_SZ commençant par %ProgramFiles% qu’écrit une application 32 bits, en les remplaçant par %ProgramFiles(x86)% (uniquement en cas de correspondance exacte, casse comprise).1 Par ailleurs, à l’époque de Vista/XP existait une « réflexion de registre » qui copiait et synchronisait les clés entre les vues 32 et 64 bits, mais elle a été supprimée à partir de Windows 7 / Windows Server 2008 R2. Gardez cette différence à l’esprit en lisant d’anciens articles sur le sujet.1
3. Clés redirigées, clés partagées
Toutes les clés ne sont pas redirigées. Certaines clés partagent une copie physique unique entre les deux vues. Voici, extrait de la liste officielle « Registry Keys Affected by WOW64 », ce qui concerne particulièrement le développement d’applications métier (colonne Windows 7 / Server 2008 R2 et versions ultérieures ; les sous-clés héritent en principe du comportement de leur parent).3
| Clé | Comportement à partir de Windows 7 |
|---|---|
HKLM\SOFTWARE |
Redirigée |
HKLM\SOFTWARE\Classes |
Partagée |
HKLM\SOFTWARE\Classes\CLSID |
Redirigée |
HKLM\SOFTWARE\Classes\Interface |
Redirigée |
HKLM\SOFTWARE\Classes\DirectShow / Media Type / MediaFoundation |
Redirigée |
HKLM\SOFTWARE\Clients |
Partagée |
HKLM\SOFTWARE\Microsoft\COM3 / EventSystem / OLE / RPC |
Partagée |
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths |
Partagée |
HKLM\SOFTWARE\Policies |
Partagée |
HKCU\SOFTWARE |
Partagée |
HKCU\SOFTWARE\Classes |
Partagée |
HKCU\SOFTWARE\Classes\CLSID / Interface |
Redirigée |
Ce qui frappe, c’est la structure imbriquée. HKLM\SOFTWARE est redirigée, mais en dessous, Classes redevient partagée, puis en dessous encore, CLSID et Interface redeviennent redirigées. Une compréhension approximative du type « tout ce qui est sous Software va dans Wow6432Node » ne peut pas expliquer la différence de comportement entre les associations d’extensions de fichiers (directement sous Classes, partagée) et l’enregistrement des classes COM (Classes\CLSID, redirigée). Autre conséquence pratique importante : HKCU est fondamentalement partagée, donc tant que les paramètres propres à l’utilisateur sont placés sous HKCU, les problèmes de bitness ne se posent quasiment pas.3
Par ailleurs, des indicateurs comme KEY_WOW64_64KEY n’ont aucun effet sur les clés partagées, puisqu’il n’en existe qu’une seule copie et que changer de vue n’a alors pas de sens.2
4. Lire explicitement une autre vue — la bonne syntaxe avec reg.exe, C# et C++
Le moyen le plus rapide de vérifier « dans quelle vue se trouve la valeur » est l’option /reg:64 / /reg:32 de reg.exe, qui accède explicitement à la vue 64 bits ou 32 bits respectivement.5
:: Lire la vue 64 bits (HKLM\Software brut)
reg query "HKLM\SOFTWARE\KomuraSoft\DeviceLink" /v LicenseKey /reg:64
:: Lire la vue 32 bits (physiquement sous Wow6432Node)
reg query "HKLM\SOFTWARE\KomuraSoft\DeviceLink" /v LicenseKey /reg:32
Si l’exécution de ces deux lignes montre une valeur d’un seul côté, cela confirme que « la bitness de celui qui a écrit et de celui qui lit ne correspond pas ». L’essentiel est de garder le même chemin logique et de ne changer que la vue, plutôt que d’écrire Wow6432Node à la main dans le chemin.
En C# (.NET), on passe un RegistryView à RegistryKey.OpenBaseKey. Il en existe trois : Registry64 (valeur 256), Registry32 (valeur 512) et Default (valeur 0), utilisables avec OpenBaseKey / OpenRemoteBaseKey / FromHandle.4
using Microsoft.Win32;
// Lire la vue 64 bits même depuis un processus 32 bits
using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
using (var key = baseKey.OpenSubKey(@"SOFTWARE\KomuraSoft\DeviceLink"))
{
var license = key?.GetValue("LicenseKey") as string;
}
// Lire la vue 32 bits (côté Wow6432Node) depuis un processus 64 bits
// ── utile par exemple pour lire, à titre transitoire, une valeur écrite par un ancien installeur 32 bits
using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
using (var key = baseKey.OpenSubKey(@"SOFTWARE\KomuraSoft\DeviceLink"))
{
var legacy = key?.GetValue("LicenseKey") as string;
}
RegistryView.Default s’en remet à la bitness du processus. Comme la bitness d’une application .NET compilée en AnyCPU varie selon l’environnement d’exécution, il est plus sûr, dès qu’il s’agit de données machine communes sous HKLM, d’expliciter dans le code quelle vue lire, afin d’éviter qu’un changement de paramètre de build (basculement de Prefer 32-bit, migration 64 bits) ne modifie soudainement la façon dont le registre est perçu. Notez que demander Registry64 sur un OS 32 bits renvoie, par spécification, la clé de la vue 32 bits : le même code reste donc sûr même si la prise en charge d’un OS 32 bits subsiste.4
En C++ (API Win32), on indique KEY_WOW64_64KEY (0x0100) ou KEY_WOW64_32KEY (0x0200) par un OU logique dans le samDesired de RegOpenKeyEx / RegCreateKeyEx / RegDeleteKeyEx. Spécifier les deux en même temps échoue avec ERROR_INVALID_PARAMETER.2
HKEY hKey = nullptr;
// Ouvrir la clé de la vue 64 bits depuis un processus 32 bits
LSTATUS st = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\KomuraSoft\\DeviceLink",
0,
KEY_READ | KEY_WOW64_64KEY, // La vue est explicitée ici
&hKey);
if (st == ERROR_SUCCESS)
{
wchar_t buf[256]; DWORD cb = sizeof(buf); DWORD type = 0;
RegQueryValueExW(hKey, L"LicenseKey", nullptr, &type,
reinterpret_cast<LPBYTE>(buf), &cb);
RegCloseKey(hKey);
}
La documentation officielle mentionne deux précautions. Une fois une autre vue ouverte avec un indicateur, il faut continuer à préciser le même indicateur pour toutes les opérations sur les sous-clés (création, suppression, ouverture) : les mélanger produit un comportement imprévisible. De plus, pour énumérer sans en manquer les clés des deux vues, il faut effectuer deux passes : une avec le handle ouvert via KEY_WOW64_64KEY, une autre via KEY_WOW64_32KEY. Notez aussi que RegDeleteKey (sans le suffixe Ex) ne peut pas accéder à une autre vue.2
5. La virtualisation de registre UAC — une valeur censée être dans HKLM se retrouve dans VirtualStore
Un autre mécanisme, souvent confondu avec la redirection, est la virtualisation de registre UAC. Ce n’est pas une question de bitness mais de droits : c’est une technologie de compatibilité introduite depuis Vista pour secourir les anciennes applications écrites en supposant des droits administrateur.6
Voici comment cela fonctionne. Lorsqu’un processus sans droit d’écriture tente d’écrire une valeur ou de créer une sous-clé sous HKLM\Software, au lieu d’échouer par refus d’accès, l’écriture est transférée vers le magasin virtuel propre à l’utilisateur HKEY_USERS\<SID utilisateur>_Classes\VirtualStore\Machine\Software (visible dans regedit sous HKCU\Software\Classes\VirtualStore\Machine\Software). De plus, à la lecture, c’est une vue fusionnée entre la valeur du magasin virtuel et celle du magasin global d’origine qui est renvoyée, la valeur du magasin virtuel étant prioritaire en cas de même nom.6 Notez que, pour un processus 32 bits sur un OS 64 bits, la redirection WOW64 du chapitre 3 s’applique d’abord, si bien que la destination réelle du transfert pour une écriture dans HKLM\Software\MyApp devient VirtualStore\Machine\Software\Wow6432Node\MyApp. En examinant le VirtualStore, vérifiez toujours aussi bien le côté Software brut que le côté Wow6432Node.
Autrement dit, le processus qui a écrit peut lire et écrire comme si de rien n’était. C’est l’origine de ces incidents étranges et dépendants de l’utilisateur : « ça marche sur le poste de développement (exécuté en administrateur), mais les paramètres sont détraqués uniquement sur le poste standard du client », ou « ça marche avec la session de M. A, mais revient aux valeurs par défaut avec celle de Mme B ». Le magasin virtuel fait partie du profil utilisateur (NTUSER.DAT, etc.), donc son contenu diffère d’un utilisateur à l’autre (pour la structure du profil, voir « Introduction aux profils utilisateur Windows - AppData et NTUSER.DAT »).
Les conditions de déclenchement de la virtualisation sont précises et explicitement décrites dans la documentation officielle.6
- Elle ne concerne que les opérations d’un processus interactif 32 bits, sous
HKLM\Software, sur une clé qu’un administrateur pourrait écrire - Sont exclus : les processus 64 bits, les processus non interactifs comme les services, les opérations en cours d’emprunt d’identité (impersonation), les pilotes, et les processus dont le manifeste indique
requestedExecutionLevel - Sont également exclus les sous-arborescences
HKLM\Software\Classes,HKLM\Software\Microsoft\WindowsetHKLM\Software\Microsoft\Windows NT
Ce qui compte particulièrement en pratique, c’est que le comportement change selon la présence ou non d’un manifeste. Comme l’éditeur de liens C++ de Visual Studio intègre par défaut un fragment UAC asInvoker dans le manifeste7, un EXE compilé avec une chaîne d’outils moderne est d’emblée exclu de la virtualisation. On ne rencontre la virtualisation que sur d’anciens EXE dépourvus de manifeste — issus de VB6, d’anciens Delphi ou d’ancien VC++ — exécutés sur Windows 64 bits. À l’inverse, un piège apparaît au moment de la migration : « juste ajouter un manifeste » ou « recompiler en 64 bits » sur un ancien EXE désactive la virtualisation, et l’écriture qui « fonctionnait » jusque-là échoue soudain par refus d’accès (ou échoue silencieusement). Les trois valeurs de requestedExecutionLevel (asInvoker / highestAvailable / requireAdministrator) et la philosophie de conception des droits sont traitées en détail dans « Quand les privilèges administrateur sont-ils nécessaires sous Windows ? ».
Il faut insister sur un point : la documentation officielle précise clairement que la virtualisation est une technologie de compatibilité provisoire (interim), que Microsoft a l’intention de supprimer dans une future version de Windows. En dépendre dans un nouveau développement est hors de question ; le principe de conception est « l’application n’écrit pas dans une zone système sensible (HKLM) : les données vont dans un emplacement propre à l’utilisateur, ou dans un emplacement commun avec une ACL adaptée ».6 Le choix de l’emplacement de stockage est détaillé dans « Comment choisir l’emplacement de stockage des données locales d’une application Windows ».
Il existe aussi des indicateurs contrôlant la virtualisation au niveau d’une clé (REG_KEY_DONT_VIRTUALIZE / REG_KEY_DONT_SILENT_FAIL / REG_KEY_RECURSE_FLAG), interrogeables et modifiables avec l’option flags de reg.exe. Voici l’exemple d’interrogation donné par la documentation officielle, avec sa sortie.6
C:\>reg flags HKLM\Software\AppKey1 QUERY
HKEY_LOCAL_MACHINE\Software\AppKey1
REG_KEY_DONT_VIRTUALIZE: CLEAR
REG_KEY_DONT_SILENT_FAIL: CLEAR
REG_KEY_RECURSE_FLAG: CLEAR
The operation completed successfully.
Les trois CLEAR signifient que « l’indicateur n’est pas activé », c’est-à-dire que la virtualisation fonctionne par défaut sur cette clé. Voici l’effet de chaque indicateur une fois activé (SET).6
| Indicateur | Effet une fois activé |
|---|---|
REG_KEY_DONT_VIRTUALIZE |
Désactive la virtualisation à l’écriture. La création de clé ou l’écriture de valeur avec des droits insuffisants n’est plus transférée vers VirtualStore : elle échoue directement |
REG_KEY_DONT_SILENT_FAIL |
Désactive la virtualisation à l’ouverture. Le rattrapage qui rouvre en MAXIMUM_ALLOWED une ouverture aux droits insuffisants n’a plus lieu : l’ouverture échoue |
REG_KEY_RECURSE_FLAG |
Propage l’indicateur de virtualisation de la clé parente vers ses enfants. Ne s’applique qu’aux sous-clés créées après le changement, pas aux sous-clés existantes |
Autrement dit, pour « arrêter la virtualisation seulement sur cette clé, afin de faire remonter les manques de droits », on active REG_KEY_DONT_VIRTUALIZE. Pour l’activer, on utilise SET à la place de QUERY, mais vérifiez l’ordre exact des options avec reg flags /?.
Pour une investigation, deux moyens rapides : dans l’onglet « Détails » du Gestionnaire des tâches, faites un clic droit sur les en-têtes de colonnes, puis ajoutez « Virtualisation UAC » via « Sélectionner les colonnes » afin de voir l’état de virtualisation par processus, et allez regarder sous HKCU\Software\Classes\VirtualStore s’il reste des résidus de valeurs transférées.
6. Les dégâts concrets côté installeur et enregistrement COM
Ces deux mécanismes se manifestent particulièrement en dégâts concrets au niveau de l’installeur et de l’enregistrement COM.
Le problème de bitness de l’installeur. Les paramètres qu’un installeur 32 bits (un MSI 32 bits ou un EXE d’installation 32 bits) écrit dans HKLM\Software\NomDeLaSociété finissent physiquement sous Wow6432Node. Si l’application elle-même a été recompilée en 64 bits mais que l’installeur reste réutilisé en 32 bits, on obtient exactement l’anecdote du début : « l’installeur a écrit, l’application ne peut pas lire ». Le cas inverse (installeur 64 bits, application 32 bits) pose le même problème. La parade consiste à faire correspondre, entre l’installeur et l’application, la vue dans laquelle on écrit et celle dans laquelle on lit, et, pendant la période transitoire d’une migration 64 bits, à implémenter une lecture de migration depuis l’ancien emplacement avec RegistryView.Registry32 du chapitre 4.
Le problème de bitness de l’enregistrement COM. Comme le montre le tableau du chapitre 3, HKLM\Software\Classes\CLSID (le côté HKLM de HKCR\CLSID) est redirigée. Autrement dit, l’enregistrement CLSID d’un serveur COM 32 bits va dans la vue 32 bits, celui d’un serveur 64 bits dans la vue 64 bits, et ils sont invisibles l’un pour l’autre.3 Un processus 64 bits ne peut de toute façon pas charger un serveur COM in-process en DLL 32 bits, donc cette séparation est en soi logique, mais sur le terrain, cela se traduit par « regsvr32 a enregistré, mais le client renvoie 0x80040154 (classe non enregistrée) ». regsvr32 lui-même existe en version 32 bits (côté SysWOW64) et en version 64 bits (côté System32), et c’est le choix de l’une ou l’autre qui détermine dans quelle vue l’enregistrement est écrit. Le panorama des pièges liés à l’enregistrement et à la bitness dans le développement COM/OCX/ActiveX est traité dans « Les pièges de l’enregistrement et de la bitness dans le développement COM/OCX/ActiveX », et l’option consistant à se passer entièrement de l’enregistrement de registre est traitée dans « Qu’est-ce que le Reg-Free COM ? ».
Le monde COM a une autre particularité historique. À l’époque de Vista/XP, CLSID et consorts étaient traités avec « redirection + réflexion (synchronisation entre les deux vues) », mais la réflexion a été supprimée à partir de Windows 7, et le comportement actuel est une séparation pure par vue.3 Quelques liens symboliques de compatibilité sont aussi définis, comme HKLM\SOFTWARE\Wow6432Node\Classes → HKLM\SOFTWARE\Classes\Wow6432Node, mais ils servent uniquement à secourir d’anciennes applications qui ont codé Wow6432Node en dur ; une nouvelle application ne doit pas s’appuyer dessus.3
Notez que même en surmontant la séparation du registre, d’autres règles de résolution de noms attendent le chargement de la DLL elle-même. Pour les investigations du type « introuvable », voir aussi « Le mécanisme de résolution des noms de DLL sous Windows - ordre de recherche et SxS ».
7. Dépannage — voir avec Procmon « ce qui a réellement été lu »
Même en connaissant les mécanismes, il faut observer pour déterminer, face à un incident réel, « quelle clé physique ce processus a finalement lue ». L’outil le plus efficace ici est Process Monitor (Procmon) de Sysinternals.
La procédure est simple.
- Lancez Procmon et ajoutez un filtre
Process Name is <appli-cible>.exe - Limitez l’affichage aux opérations de registre via la barre d’outils (un filtre
Operation begins with Regfonctionne aussi) - Reproduisez l’opération problématique dans l’application, et examinez les lignes
RegOpenKey/RegQueryValue/RegSetValue
Le point essentiel, c’est que la colonne Path de Procmon affiche le chemin physique après résolution de la redirection. Même si une application 32 bits croit ouvrir HKLM\Software\MyApp, Procmon affiche HKLM\SOFTWARE\WOW6432Node\MyApp. Si vous voyez une série de NAME NOT FOUND ici, il devient évident en un coup d’œil quelle vue, quelle clé, fait défaut ; et si une écriture part vers HKCU\Software\Classes\VirtualStore\..., le déclenchement de la virtualisation est également observable. Pour une investigation 0x80040154 sur COM, on peut même remonter à savoir dans quelle vue l’ouverture de CLSID\{...} a échoué. Pour le détail de la conception des filtres et de la lecture de Procmon, voir « Guide pratique de Process Monitor (ProcMon) ».
8. Les réflexes pratiques (tableau de décision)
| Situation | À faire | Raison / remarque |
|---|---|---|
| « C’est visible dans regedit mais invisible depuis l’application » | Comparer les deux vues avec reg query ... /reg:64 et /reg:32 |
Déterminer d’abord dans quelle vue se trouve la valeur5 |
| Des processus maison en 32 bits et en 64 bits lisent le même paramètre HKLM | Fixer la vue côté écriture (par exemple la vue 64 bits) et faire en sorte que tous les lecteurs explicitent la même vue | Uniformiser avec RegistryView.Registry64 / KEY_WOW64_64KEY42 |
Envie de coder en dur Wow6432Node dans le code |
Ne pas le faire. Remplacer par une API de vue explicite | L’emplacement physique est réservé au système ; sur ARM, c’est WowAA32Node12 |
| Où placer les paramètres propres à l’utilisateur | Sous HKCU (ou AppData) | HKCU est une clé partagée, sans problème de bitness ni de droits3 |
| Une ancienne application 32 bits a des paramètres « qui varient selon l’utilisateur » | Vérifier HKCU\Software\Classes\VirtualStore |
Cas typique de valeurs transférées par la virtualisation, accumulées par utilisateur6 |
| Ajouter un manifeste ou recompiler en 64 bits un ancien EXE | Le faire seulement après avoir recensé tous les points d’écriture dans HKLM | La virtualisation se désactive, et des écritures qui « fonctionnaient » jusque-là commencent à échouer67 |
| 0x80040154 sur COM | Vérifier la bitness du client et du serveur, et confirmer l’enregistrement avec le regsvr32/la vue correspondante | L’enregistrement CLSID est séparé par vue3 |
| Impossible de déterminer ce qui a été lu | Observer le chemin physique et le résultat (NAME NOT FOUND, etc.) avec Procmon | Arrêter de deviner et regarder les faits est le plus rapide |
9. Conclusion
- Le registre de Windows 64 bits possède deux vues ;
HKLM\Softwarevu par un processus 32 bits est transparemment redirigé vers Wow6432Node. C’est le premier suspect en cas de « valeur écrite introuvable ». - La redirection ne concerne pas toutes les clés. Retenez la structure imbriquée :
Classesest partagée,CLSID/Interfaceen dessous sont redirigées, et HKCU est presque entièrement partagée. - Ne codez jamais Wow6432Node en dur dans un chemin. Explicitez la vue avec
/reg:64/reg:32de reg.exe,RegistryViewen .NET, ouKEY_WOW64_64KEY/KEY_WOW64_32KEYen Win32. - La virtualisation de registre UAC transfère silencieusement vers VirtualStore une écriture HKLM effectuée avec des droits insuffisants par un processus interactif 32 bits sans manifeste. C’est une technologie provisoire de secours pour les applications héritées ; n’en dépendez jamais dans une nouvelle application.
- Faites correspondre la vue utilisée entre l’installeur et l’application, entre le serveur COM et le client. Prévoyez une lecture de migration depuis l’ancienne vue pendant la période de transition d’une migration 64 bits.
- En cas de doute, observez le chemin physique avec Procmon. Observer est plus rapide et plus fiable que deviner.
Articles connexes
- Les pièges de l’enregistrement et de la bitness dans le développement COM/OCX/ActiveX
- Qu’est-ce que le Reg-Free COM ?
- Quand les privilèges administrateur sont-ils nécessaires sous Windows ?
- Introduction aux profils utilisateur Windows - AppData et NTUSER.DAT
- Comment choisir l’emplacement de stockage des données locales d’une application Windows
- Guide pratique de Process Monitor (ProcMon)
- Le mécanisme de résolution des noms de DLL sous Windows - ordre de recherche et SxS
Domaines de conseil associés
合同会社小村ソフト (Komura Software LLC) prend en charge l’investigation d’incidents tels que « la valeur écrite dans le registre reste illisible » ou « l’enregistrement COM est introuvable », la conception de la migration 64 bits d’applications 32 bits et de composants COM existants, et le développement sous contrat d’applications métier Windows, y compris les logiciels de liaison avec des équipements.
- Investigation d’incidents et analyse des causes
- Migration et valorisation des actifs existants
- Développement de composants COM
- Contact
Références
-
Microsoft Learn, Registry Redirector. Sur le fait que le redirecteur de registre fournit des vues logiques distinctes aux applications 32 bits et 64 bits de façon transparente pour l’application, que HKEY_LOCAL_MACHINE\Software est redirigée vers HKEY_LOCAL_MACHINE\Software\Wow6432Node, que l’emplacement physique est réservé au système et ne doit pas être accédé directement par les applications, que les clés 32 bits ARM de Windows 10 on ARM sont mappées vers WowAA32Node, sur le remplacement des chaînes %ProgramFiles%, et sur la suppression de la réflexion à partir de Windows 7 / Windows Server 2008 R2. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Microsoft Learn, Accessing an Alternate Registry View. Sur la signification de KEY_WOW64_64KEY (0x0100) et KEY_WOW64_32KEY (0x0200), sur leur indication dans le samDesired de RegCreateKeyEx, RegDeleteKeyEx et RegOpenKeyEx, sur le fait qu’indiquer les deux indicateurs simultanément produit ERROR_INVALID_PARAMETER, qu’ils sont sans effet sur les clés partagées, qu’il faut continuer à utiliser le même indicateur pour les opérations sur les sous-clés, que l’énumération complète des clés nécessite deux passes, et sur le fait que Wow6432Node/WowAA32Node sont des clés réservées. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Microsoft Learn, Registry Keys Affected by WOW64. Sur la liste des clés redirigées et partagées (à partir de Windows 7, HKLM\SOFTWARE est redirigée, HKLM\SOFTWARE\Classes est partagée, Classes\CLSID, Interface, DirectShow etc. sont redirigées, Clients, COM3, OLE, RPC, App Paths, Policies, HKCU\SOFTWARE etc. sont partagées), sur le fait que les sous-clés héritent du comportement du parent, sur le fait que HKCR est une vue fusionnée des Classes de HKLM et HKCU, et sur le fait que les liens symboliques de compatibilité incluant Wow6432Node servent à secourir des applications existantes et ne doivent pas être utilisés par de nouvelles applications. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9
-
Microsoft Learn, RegistryView Enum (Microsoft.Win32). Sur l’énumération RegistryView avec Default (0), Registry64 (256) et Registry32 (512), sur la possibilité d’indiquer la vue via OpenBaseKey, OpenRemoteBaseKey et FromHandle, et sur le fait que demander la vue 64 bits sur un OS 32 bits renvoie la clé de la vue 32 bits. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, reg query. Sur le fait que l’option /reg:32 de la commande reg query accède à la clé via la vue de registre 32 bits, et /reg:64 via la vue 64 bits. ↩ ↩2 ↩3
-
Microsoft Learn, Registry Virtualization. Sur le fait qu’une écriture dans HKLM\Software est redirigée vers
HKEY_USERS\<SID utilisateur>_Classes\VirtualStore\Machine\Software, qu’une vue fusionnée priorisant le magasin virtuel est renvoyée à la lecture, que la virtualisation ne s’applique qu’à un processus interactif 32 bits, sous HKLM\Software, sur une clé qu’un administrateur pourrait écrire, qu’elle est désactivée pour les processus 64 bits, les services, les opérations en impersonation, les processus avec requestedExecutionLevel indiqué et les sous-clés telles que Classes, qu’il s’agit d’une technologie de compatibilité provisoire vouée à disparaître et sur laquelle une application ne doit pas compter, et sur le contrôle via reg flags de REG_KEY_DONT_VIRTUALIZE et autres indicateurs. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 -
Microsoft Learn, Application manifests. Sur la signification des valeurs asInvoker, requireAdministrator et highestAvailable de l’élément requestedExecutionLevel, sur le fait qu’indiquer un nœud requestedExecutionLevel désactive la virtualisation des fichiers et du registre, sur le fait qu’il faut omettre ce nœud pour continuer à bénéficier de la virtualisation par rétrocompatibilité, et sur le fait que l’éditeur de liens Visual C++ intègre par défaut un fragment UAC asInvoker dans le manifeste. ↩ ↩2 ↩3
Articles associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
Comment choisir où une application Windows stocke ses données locales — tableau de décision pour SQLite / JSON / Registre / Access
Où et sous quelle forme une application de bureau Windows doit-elle stocker ses données ? Cet article organise le choix entre AppData et ...
Bonnes pratiques de multithreading en pratique — édition .NET : ce qu'il faut décider avant d'ajouter des threads
Un ensemble de bonnes pratiques de conception pour .NET/C# afin d'éviter que « démarrer un thread » ne fasse planter ou geler l'applicati...
Utiliser WMI/CIM depuis C# et PowerShell — Guide pratique pour la récupération d'informations matérielles, la surveillance des processus et l'interrogation à distance
La récupération du numéro de série d'un PC, la surveillance de l'espace disque libre et la détection du démarrage de processus reposent c...
Jusqu'à quand peut-on utiliser MSMQ ? — La décision de migration d'une file d'attente héritée « qui n'est même pas dépréciée »
MSMQ ne figure sur aucune liste officielle de dépréciation, mais System.Messaging n'existe que dans .NET Framework, ce qui bloque la migr...
Le TPM sous Windows expliqué en images — le « coffre-fort qui ne laisse jamais sortir la clé » et le démarrage mesuré
Explique le TPM en images : le mécanisme qui empêche la clé de sortir de la puce, les PCR et le démarrage mesuré, son usage dans BitLocke...
Sujets associés
Ces pages replacent le sujet dans un contexte plus large de services et de décisions.
Thèmes techniques Windows
Portail des sujets sur le développement Windows, l'analyse des incidents et la valorisation des actifs existants.
Services liés à ce sujet
Cet article est directement lié aux services suivants.
Développement d'applications Windows
Applications métier, intégration d'équipements et outils de communication, des besoins au développement.
Questions fréquentes
Questions souvent posées lors d’une consultation sur le sujet de cet article.
- Pourquoi la valeur est-elle visible dans regedit, mais absente quand l'application la lit ?
- La cause typique est que l'application et regedit ne regardent pas la même vue du registre. Sous Windows 64 bits, regedit s'exécute en tant que processus 64 bits et affiche, à partir de la vue 64 bits, y compris Wow6432Node (l'emplacement physique de la vue 32 bits). En revanche, quand une application 32 bits ouvre HKLM\Software, le redirecteur de registre WOW64 l'oriente vers le côté Wow6432Node, si bien qu'une valeur qui n'existe que du côté vue 64 bits « n'existe pas » pour elle. Vérifiez d'abord si le chemin de la valeur visible dans regedit contient Wow6432Node, puis comparez les deux vues avec /reg:64 et /reg:32 de reg query pour isoler rapidement le problème.
- Peut-on accéder directement au chemin Wow6432Node depuis le code ?
- Non, il faut l'éviter. La documentation officielle de Microsoft précise clairement que l'emplacement physique de redirection est une zone réservée du système, susceptible de changer à l'avenir, et qu'une application ne doit pas y accéder directement. En effet, sur Windows 10 on ARM, un emplacement physique différent, WowAA32Node, est utilisé pour les applications ARM 32 bits : coder Wow6432Node en dur échoue donc sur environnement ARM. Pour accéder à une autre vue, utilisez les moyens officiels que sont les indicateurs KEY_WOW64_64KEY/KEY_WOW64_32KEY ou RegistryView en .NET.
- Pourquoi une valeur que je pensais avoir écrite dans HKLM se retrouve-t-elle dans le VirtualStore de HKCU ?
- C'est le résultat de la virtualisation de registre UAC. Lorsqu'un processus interactif 32 bits sans droit d'écriture, dont le manifeste ne comporte pas requestedExecutionLevel, écrit sous HKLM\Software, l'écriture n'échoue pas : elle est transférée vers le magasin virtuel propre à l'utilisateur (HKEY_USERS\<SID>_Classes\VirtualStore\Machine\Software, visible dans regedit sous HKCU\Software\Classes\VirtualStore). Comme ce même processus, en relisant, voit une vue fusionnée entre le magasin virtuel et l'emplacement d'origine, tout semble fonctionner à première vue ; mais un processus 64 bits ou un service ne voit pas cette valeur, d'où l'incident étrange où « le paramètre diffère selon l'utilisateur ». La virtualisation étant une technologie provisoire de secours pour les applications héritées, une nouvelle application ne doit jamais en dépendre.
- Comment expliciter en C# la bitness (vue 32 bits/64 bits) du registre ?
- En passant un RegistryView à RegistryKey.OpenBaseKey. Indiquer RegistryView.Registry64 permet de lire et d'écrire la vue 64 bits même depuis un processus 32 bits ; indiquer RegistryView.Registry32 permet de lire et d'écrire la vue 32 bits (côté Wow6432Node) même depuis un processus 64 bits. RegistryView.Default s'en remet à la bitness du processus, donc pour une configuration où la bitness varie selon l'environnement d'exécution, comme un build AnyCPU, il est plus sûr d'expliciter quelle vue lire. Notez que demander Registry64 sur un OS 32 bits renvoie, par spécification, la vue 32 bits : le même code fonctionne donc même si la prise en charge d'un OS 32 bits subsiste.
- Comment désactiver la virtualisation de registre, ou vérifier si elle est active ?
- Côté application, indiquer requestedExecutionLevel dans le manifeste (asInvoker suffit) désactive la virtualisation des fichiers et du registre pour ce processus. Côté administration, la commande reg flags permet de définir et de vérifier l'indicateur REG_KEY_DONT_VIRTUALIZE au niveau d'une clé. Pour investiguer une application déjà en service, le plus rapide est de vérifier l'état de virtualisation par processus dans la colonne « Virtualisation UAC » du Gestionnaire des tâches, et de regarder si des valeurs transférées se sont accumulées sous HKCU\Software\Classes\VirtualStore. Comme mesure durable, nous recommandons de revoir la conception pour ne pas écrire dans HKLM du tout (placer les paramètres propres à l'utilisateur dans HKCU ou AppData).
Profil de l’auteur
Page de présentation de l’auteur de l’article.
Go Komura
Représentant de KomuraSoft LLC
Spécialisé dans le développement de logiciels Windows, le conseil technique et l’analyse de pannes, notamment pour les systèmes existants et les incidents difficiles à reproduire.