IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

Réponse différente entre Win32 et Win64 !


Sujet :

Delphi

  1. #1
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    849
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 849
    Points : 1 174
    Points
    1 174
    Par défaut Réponse différente entre Win32 et Win64 !
    Bonjour j'ai un résultat différent en fonction si je compile en Win32 ou en Win64 sur l'API GetTokenInformation dans la fonction suivante !

    Auriez-vous une idée du pourquoi de ce étrange phénomène ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    function TForm1.IsProcessOwnedByUser(ProcessID: Cardinal): Boolean;
    var
      hToken: NativeUInt;
      TokenInformation: array[0..1023] of Byte;
      TokenUser: PTokenUser;
      dwSize: Cardinal;
      hProcess: NativeUInt;
      UserSID: SID_NAME_USE;
      LResult: LongBool;
      AccountName: array[0..255] of WideChar;
      DomainName: array[0..255] of WideChar;
      cbAccountName, cbDomainName: Cardinal;
      CurrentUserName: String;
    begin
      Result := False;
     
      hProcess := OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcessID);
     
      if hProcess = 0 then
        Exit;
     
      try
        if OpenProcessToken(hProcess, TOKEN_QUERY, hToken) then
        try
          dwSize := SizeOf(TokenInformation);
     
          LResult := GetTokenInformation(hToken, TTokenInformationClass.TokenUser, @TokenInformation, dwSize, dwSize);
     
          if LResult then
          begin
            TokenUser     := PTokenUser(@TokenInformation);
            cbAccountName := SizeOf(AccountName);
            cbDomainName  := SizeOf(DomainName);
     
            LookupAccountSid(nil, TokenUser.User.Sid, AccountName, cbAccountName, DomainName, cbDomainName, UserSID);
     
            CurrentUserName := GetCurrentUserName;
            Result          := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, AccountName, -1, PChar(CurrentUserName), -1) = CSTR_EQUAL;
          end;
        finally
          CloseHandle(hToken);
        end;
      finally
        CloseHandle(hProcess);
      end;
    end;

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 612
    Points : 25 303
    Points
    25 303
    Par défaut
    je n'utiliserais pas dwSize pour TokenInformationLength et ReturnLength, par exemple



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    function IsServiceProcess(): Boolean;
    var
      TokenHandle: THandle;
      TokenSessionId: DWORD;
      TokenInformationLength: DWORD;
    begin
      Result := False;
      TokenInformationLength := SizeOf(TokenSessionId);
      ReturnLength := 0;
      if not OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, TokenHandle) then
        Exit;
     
      try
        if not GetTokenInformation(TokenHandle, TTokenInformationClass.TokenSessionId, @TokenSessionId, TokenInformationLength, ReturnLength) then
          RaiseLastOSError();
     
        if ReturnLength = 0 then
          Exit;
     
        Result := TokenSessionId = 0;
      finally
        CloseHandle(TokenHandle);
      end;
    end;


    Mais c'est quoi différent ?
    Après tout, le 32bit est émulé, qu'il y ait une différence, n'est pas si surprenant, cela peut émuler des valeurs telles qu'elles étaient dans une version antérieure de l'OS
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 789
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 789
    Points : 13 449
    Points
    13 449
    Par défaut
    Je laisserais GetTokenInformation retourner la taille nécessaire plutôt que la fixer en dur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if GetTokenInformation(hToken, TokenUser, nil, 0, dwSize) or (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
    et ensuite seulement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    TokenInformation := GetMem(dwSize);
     
    if not GetTokenInformation(hToken, TokenUser, TokenInformation, dwSize, dwSize) then Exit;
     
    ...

  4. #4
    Expert éminent Avatar de sergio_is_back
    Homme Profil pro
    Consultant informatique industrielle, développeur tout-terrain
    Inscrit en
    Juin 2004
    Messages
    1 162
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Consultant informatique industrielle, développeur tout-terrain
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 162
    Points : 6 034
    Points
    6 034
    Par défaut
    Comme le demande ShaiLeTroll en quoi le résultat est-il différent, ce serai intéressant que tu nous donnes l'information...

  5. #5
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    849
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 849
    Points : 1 174
    Points
    1 174
    Par défaut
    Sur les mêmes processus, en WIN32, la réponse LRresult est à TRUE et en Win64, LRresult est à FALSE !

    Mon système est en Win64, et mon Delphi est le 11.2.

    Je vais regarder à améliorer mon code avec vos remontées.

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 612
    Points : 25 303
    Points
    25 303
    Par défaut
    Citation Envoyé par der§en Voir le message
    Sur les mêmes processus, en WIN32, la réponse LRresult est à TRUE et en Win64, LRresult est à FALSE !
    d'où le RaiseLastOSError(); pour avoir une information complémentaire

    et la variante en deux temps avec ERROR_INSUFFICIENT_BUFFER pour vérifier la taille du buffer, si pour TokenSessionId qui est toujours un DWORD pour TokenUser qui retourne un TOKEN_USER, ce n'est pas une mauvaise idée même si en utilisant directement un TTokenUser
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 789
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 789
    Points : 13 449
    Points
    13 449
    Par défaut
    Un petit essai ce matin et effectivement il y a un problème d'accès à la pile en 64 bits. Donc passer par GetMem.

    Juste pour confirmation, déclarer TokenInformation en variable globale et là ça passe.

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 612
    Points : 25 303
    Points
    25 303
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Un petit essai ce matin et effectivement il y a un problème d'accès à la pile en 64 bits. Donc passer par GetMem
    Et a noter que le buffer allouée fait 36 et 44 selon 32/64 bits, cela doit être la place pour allouer le pointer de type PSID : https://learn.microsoft.com/fr-fr/wi...t/ns-winnt-sid

    Dans ce cas ça devient (j'ai utilisé ma version de GetCurrentUserName n'ayant pas celle utilisée par der§en)

    On peut directement le pointer PTokenUser mais en l'allouant manuellement à la taille requise pour les pointeurs imbriqués

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    function IsProcessOwnedByUser(ProcessID: Cardinal): Boolean;
     
      function GetTokenUser(ATokenHandle: THandle): PTokenUser;
      var
        TokenInformationLength, ReturnLength: DWORD;
        LastError: DWORD ;
      begin
        TokenInformationLength := SizeOf(Result);
        ReturnLength := 0;
        GetTokenInformation(ATokenHandle, TTokenInformationClass.TokenUser, nil, 0, ReturnLength);
        LastError := GetLastError();
        if (LastError = ERROR_INSUFFICIENT_BUFFER) and (TokenInformationLength <= ReturnLength) then
        begin
          GetMem(Result, ReturnLength);
          try
            if not GetTokenInformation(ATokenHandle, TTokenInformationClass.TokenUser, Result, ReturnLength, ReturnLength) then
              RaiseLastOSError();
          except
            FreeMem(Result);
            raise;
          end;
        end
        else
          RaiseLastOSError(LastError);
      end;
     
      procedure ReleaseTokenUser(var ATokenUser: PTokenUser);
      begin
        FreeMem(ATokenUser);
        ATokenUser := nil;
      end;
     
      type
        _USER_NAME_FORMAT = (NameUnknown,
          NameFullyQualifiedDN, NameSamCompatible,
          NameDisplay, NameUniqueId = 6,
          NameCanonical, NameUserPrincipal,
          NameCanonicalEx, NameServicePrincipal,
          NameDnsDomain = 12);
        TUserNameFormat = _USER_NAME_FORMAT;
     
      const
        Secur32 = 'Secur32.dll';
        UNLEN = 256; // A buffer size of (UNLEN + 1) characters will hold the maximum length user name including the terminating null character. UNLEN is defined in Lmcons.h.
     
      function GetCurrentUserName(NameFormat: TUserNameFormat = NameUnknown): string;
      var
        AccountName: array[0..UNLEN] of WideChar;
        cbAccountName: DWORD;
        Secur32H: HMODULE;
        GetUserNameEx: function(NameFormat: TUserNameFormat; lpBuffer: PWideChar; var nSize: DWORD): BOOL; stdcall;
      begin
        Result := '';
        cbAccountName := MAX_PATH;
        if NameFormat <> NameUnknown then
        begin
          Secur32H := LoadLibrary(Secur32);
          if Secur32H <> 0 then
          try
            GetUserNameEx := GetProcAddress(Secur32H, 'GetUserNameExW');
            if Assigned(GetUserNameEx) and GetUserNameEx(NameFormat, AccountName, cbAccountName) then
              Result := AccountName;
          finally
            FreeLibrary(Secur32H);
          end;
        end
        else
          if GetUserName(AccountName, cbAccountName) then
            Result := AccountName;
      end;
     
     
    var
      hProcess: THandle;
      hToken: THandle;
      TokenUser: PTokenUser;
     
      UserSID: SID_NAME_USE;
      AccountName: array[0..255] of WideChar;
      DomainName: array[0..255] of WideChar;
      cbAccountName, cbDomainName: Cardinal;
      CurrentUserName: String;
    begin
      Result := False;
     
      hProcess := OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcessID);
      if hProcess = 0 then
        Exit;
     
      try
        if OpenProcessToken(hProcess, TOKEN_QUERY, hToken) then
        try
          TokenUser := GetTokenUser(hToken);
          try
            cbAccountName := SizeOf(AccountName);
            cbDomainName  := SizeOf(DomainName);
     
            LookupAccountSid(nil, TokenUser.User.Sid, AccountName, cbAccountName, DomainName, cbDomainName, UserSID);
     
            CurrentUserName := GetCurrentUserName();
            Result          := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, AccountName, -1, PChar(CurrentUserName), -1) = CSTR_EQUAL;
          finally
            ReleaseTokenUser(TokenUser);
          end;
        finally
          CloseHandle(hToken);
        end;
      finally
        CloseHandle(hProcess);
      end;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    procedure TForm1.Button3Click(Sender: TObject);
    begin
      ShowMessage(BoolToStr(IsProcessOwnedByUser(GetCurrentProcessId()), True));
    end;


    Une autre variante un peu plus simple mais j'ai peur que cela invalide les pointeurs imbriqués comme SID

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
     
    function IsProcessOwnedByUser(ProcessID: Cardinal): Boolean;
     
      function GetTokenUser(TokenHandle: THandle): TTokenUser;
      var
        TokenInformationLength, ReturnLength: DWORD;
        TokenInformation: Pointer;
        LastError: DWORD ;
      begin
        TokenInformationLength := SizeOf(Result);
        ReturnLength := 0;
        GetTokenInformation(TokenHandle, TTokenInformationClass.TokenUser, nil, 0, ReturnLength);
        LastError := GetLastError();
        if (LastError = ERROR_INSUFFICIENT_BUFFER) and (TokenInformationLength <= ReturnLength) then
        begin
          GetMem(TokenInformation, ReturnLength);
          try
            if GetTokenInformation(TokenHandle, TTokenInformationClass.TokenUser, TokenInformation, ReturnLength, ReturnLength) then
              Result := PTokenUser(TokenInformation)^
            else
              RaiseLastOSError();
          finally
            FreeMem(TokenInformation);
          end;
        end
        else
          RaiseLastOSError(LastError);
      end;
     
      type
        _USER_NAME_FORMAT = (NameUnknown,
          NameFullyQualifiedDN, NameSamCompatible,
          NameDisplay, NameUniqueId = 6,
          NameCanonical, NameUserPrincipal,
          NameCanonicalEx, NameServicePrincipal,
          NameDnsDomain = 12);
        TUserNameFormat = _USER_NAME_FORMAT;
     
      const
        Secur32 = 'Secur32.dll';
        UNLEN = 256; // A buffer size of (UNLEN + 1) characters will hold the maximum length user name including the terminating null character. UNLEN is defined in Lmcons.h.
     
      function GetCurrentUserName(NameFormat: TUserNameFormat = NameUnknown): string;
      var
        AccountName: array[0..UNLEN] of WideChar;
        cbAccountName: DWORD;
        Secur32H: HMODULE;
        GetUserNameEx: function(NameFormat: TUserNameFormat; lpBuffer: PWideChar; var nSize: DWORD): BOOL; stdcall;
      begin
        Result := '';
        cbAccountName := MAX_PATH;
        if NameFormat <> NameUnknown then
        begin
          Secur32H := LoadLibrary(Secur32);
          if Secur32H <> 0 then
          try
            GetUserNameEx := GetProcAddress(Secur32H, 'GetUserNameExW');
            if Assigned(GetUserNameEx) and GetUserNameEx(NameFormat, AccountName, cbAccountName) then
              Result := AccountName;
          finally
            FreeLibrary(Secur32H);
          end;
        end
        else
          if GetUserName(AccountName, cbAccountName) then
            Result := AccountName;
      end;
     
     
    var
      hProcess: THandle;
      hToken: THandle;
      TokenUser: TTokenUser;
     
      UserSID: SID_NAME_USE;
      AccountName: array[0..255] of WideChar;
      DomainName: array[0..255] of WideChar;
      cbAccountName, cbDomainName: Cardinal;
      CurrentUserName: String;
    begin
      Result := False;
     
      hProcess := OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcessID);
      if hProcess = 0 then
        Exit;
     
      try
        if OpenProcessToken(hProcess, TOKEN_QUERY, hToken) then
        try
          TokenUser     := GetTokenUser(hToken);
          cbAccountName := SizeOf(AccountName);
          cbDomainName  := SizeOf(DomainName);
     
          LookupAccountSid(nil, TokenUser.User.Sid, AccountName, cbAccountName, DomainName, cbDomainName, UserSID);
     
          CurrentUserName := GetCurrentUserName();
          Result          := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, AccountName, -1, PChar(CurrentUserName), -1) = CSTR_EQUAL;
        finally
          CloseHandle(hToken);
        end;
      finally
        CloseHandle(hProcess);
      end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Membre éprouvé Avatar de der§en
    Homme Profil pro
    Chambord
    Inscrit en
    Septembre 2005
    Messages
    849
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Chambord
    Secteur : Transports

    Informations forums :
    Inscription : Septembre 2005
    Messages : 849
    Points : 1 174
    Points
    1 174
    Par défaut
    Merci a vous 3 pour l'aide apporté a la résolution de mon problème

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Lazarus] Changer Win32 en Win64
    Par ChPr dans le forum Lazarus
    Réponses: 8
    Dernier message: 26/01/2020, 13h05
  2. [Divers] Conversion d'applications win32 en win64
    Par freud dans le forum Outils
    Réponses: 2
    Dernier message: 12/04/2016, 08h03
  3. [LAPACK] installation pour Win32 et Win64
    Par FrankOVD dans le forum Bibliothèques et frameworks
    Réponses: 0
    Dernier message: 26/11/2013, 22h52
  4. Win32 vs Win64 - runtime error en 64 bits
    Par Slookeur dans le forum GTK+ avec C & C++
    Réponses: 2
    Dernier message: 05/04/2012, 15h02
  5. Problème entre win32 et Ubuntu
    Par bobkiller dans le forum GTK+ avec C & C++
    Réponses: 4
    Dernier message: 15/12/2006, 15h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo