diff --git a/CLAUDE.md b/CLAUDE.md index 47bd892..3e1ae02 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -293,7 +293,14 @@ que dans une charge utile dont on sait deja qu'elle vient de nous. courriel, et l'UUID brut de la carte mere est un identifiant materiel unique qui n'a pas a circuler en clair ni a finir dans nos journaux. - UUID lu par WMI (`Win32_ComputerSystemProduct`, COM via `Winapi.ActiveX` pour - `IEnumVariant`). **Un UUID nul ou tout a FF est rejete** : beaucoup de VM et + `IEnumVariant`). **`BoardUUID` appelle `CoInitializeEx` lui-meme** : sans ca + l'empreinte dependait de qui avait demarre avant — apres l'init de WebView2 + elle lisait le vrai UUID, avant elle echouait et retombait sur `MachineGuid`, + soit DEUX empreintes pour une seule machine et une licence liee a l'une que + l'autre refuse. Un identifiant qui depend de l'ordre de demarrage n'est pas un + identifiant. **Et on ne fait PAS de `CoUninitialize` symetrique** : il parait + propre et se paie d'une violation d'acces, les mandataires WMI et le cache de + type-info de ComObj se liberant plus tard, dans un appartement ferme. **Un UUID nul ou tout a FF est rejete** : beaucoup de VM et d'images clonees l'annoncent, et s'en contenter ferait tomber des postes differents sur la MEME empreinte — une licence emise pour l'un ouvrirait chez l'autre. Repli sur `MachineGuid` (HKLM\...\Cryptography), distinct par diff --git a/delphi-backend/Source/PM.MachineId.pas b/delphi-backend/Source/PM.MachineId.pas index 93c9c9b..ad38cb9 100644 --- a/delphi-backend/Source/PM.MachineId.pas +++ b/delphi-backend/Source/PM.MachineId.pas @@ -53,6 +53,23 @@ var LFetched: LongWord; begin Result := ''; + + // COM DOIT ETRE INITIALISE ICI, PAS AILLEURS PAR CHANCE. + // + // Sans ca, l'empreinte depend de qui a demarre avant nous : appelee apres + // l'initialisation de WebView2 elle lit le vrai UUID de la carte mere, + // appelee avant elle echoue et retombe sur MachineGuid — DEUX empreintes + // differentes pour une seule machine, et une licence liee a l'une que + // l'autre refuse. Un identifiant qui depend de l'ordre de demarrage n'est + // pas un identifiant. + // + // ET ON NE LIBERE PAS. Un CoUninitialize symetrique parait propre et se + // paie d'une violation d'acces : les mandataires WMI et le cache de + // type-info de ComObj survivent a l'appel et se liberent plus tard, dans un + // appartement qui n'existe plus. Laisser l'appartement ouvert pour la duree + // du processus ne coute rien ici — cette application heberge WebView2, donc + // COM y est de toute facon initialise et le reste. + CoInitializeEx(nil, COINIT_APARTMENTTHREADED); try LLocator := CreateOleObject('WbemScripting.SWbemLocator'); LServices := LLocator.ConnectServer('.', 'root\CIMV2');