Jump to content

Davide Angeli

Members
  • Content Count

    116
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by Davide Angeli


  1. 1 hour ago, Lars Fosdal said:

    Do you stop the tasks and wait for completion of any running task before stopping the application?

    Before posting I tried several solutions, some of these suggested in this post: 

     

    According to Primoz OTL book it seems to be enough to assign the IOmniTimedTask instance to nil to get the call to Terminate(INFINITE) and Terminate should stop the task... This works perfectley in a little sample demo. In my case leads to random errors (the app is very complex).

     

    I've tried calling the Stop method and then assign the instance to nil but I get the random errors too.

     

    I've tried calling also Stop + Terminate(INFINTE) + WaitFor(INFINITE) + assigning to nil without results

     

     


  2. I recently started using Parallel.TimedTask and now when I close the application I get the same error in completely random mode. I can't simulate the problem in a small project. I'm using D11.3 and the latest OTL version. Some idea?


  3. 7 hours ago, AndrewHoward said:

    I tried File -> New -> Other -> WSDL Importer -> enter the above link but I get an error.

     

    Maybe the problem could be that the WSDL contains an xsl stylesheet. 

    Have you tried downloading the wsdl source to a disk file and then importing into Delphi from that local file?


  4. I solved this thanks to the kind collaboration of the nSoftware assistance service (SecureBlackBox's developer). 

     

    There were many challenges to solve to achieve the goal and very little can be found online. It is my understanding that this type of security is not used much in the Delphi environment. However I solved by combining several components provided with the SecurityBlackBox suite:

    • TsbxCertificateStorage to read JKS file to reach public key (used to encrypt the request and verify the signed response) and private key (used to sign the request and decrypt the response)

    • TsbxSOAPSigner to sign the SOAP request (to produce a WSSSignature)
    • TsbxXMLEncryptor to embed in the request the encryption key (transported with RSA-OAEP sha1) and to crypt the SOAP request body (with AES128 algorithm)
    • TsbxXMLDecryptor to decrypt the response (two items encrypted in the response: the sign and the body)
    • TsbxSOAPVerifier to verifiy the sign in the response

    I've injected this encryption/decryption stuff in THTTPRio events, somthing like this;

    procedure TMultyAssociativeServiceWrapper.SOAPOnBeforeExecute(const MethodName: String; SOAPRequest: TStream);
    begin
      // save the original request (created by THTTPRio) for debug purpose
      SOAPRequest.Seek(0,0);
      (SOAPRequest as TMemoryStream).SaveToFile(FFileRequestOriginal);
    
      // sign and encrypt the original request
      SBBSoapSignAndEncryptWithJKS(FFileRequestOriginal, FFileRequestToSend, FCertificateFileJKS, OnPasswordNeeded);
      
      // ... do some other stuff ?
    
      // update the outcoming request with the signed crypted version
      SOAPRequest.Seek(0,0);
      (SOAPRequest as TMemoryStream).LoadFromFile(FFileRequestToSend);
    end;
    
    procedure TMultyAssociativeServiceWrapper.SOAPOnAfterExecute(const MethodName: String; SOAPResponse: TStream);
    begin
      // save te orginal response arrived from service for debug purpose
      SOAPResponse.Seek(0,0);
      (SOAPResponse as TMemoryStream).SaveToFile(FFileResponseOriginal);
    
      // decrypt and verify sign of response
      SBBSoapDecryptAndVerifyWithJKS(FFileResponseOriginal, FFileResponseDecoded, FCertificateFileJKS,  OnPasswordNeeded);
      
      //... do some other stuff?
    
      // update the incoming response with the decrypted data
      SOAPResponse.Seek(0,0);
      (SOAPResponse as TMemoryStream).LoadFromFile(FFileResponseDecoded);
    end;

     

    SBBSoapSignAndEncryptWithJKS does sign + encryption stuff.

    SBBSoapDecryptAndVerifyWithJKS does decrypt and verify sign stuff.

     

    I hope this can be helpful for someone else who runs into this need. If you need the code of the two SBB procedures described above please ask me.

     

    I've used SecureBlackBox components but I think that same stuff could be reached also with ChilKat library. I did some tests with the demo library, it works at a lower level of SBB but there are several examples online that could be combined to reach the goal.

    • Like 2
    • Thanks 1

  5. On 1/28/2023 at 9:55 AM, mjustin said:

    Have you compared the requests from SoapUI with the requests sent from your code?

    Yes, with SBB is not possibile to reach the same request without doing some further manipulation of the xml and it misses also the reference list for decryption. I'm working on that and another problem I think should be the order of doing operations: I'm doing crypt+sign but I'm investigating  if service aspect sign and then crypt.  I will do theese changes but I could not test because of server down for maintenance. I'll report the results.


  6. Hi all,

     

    I'm really becaming crazy trying to do this with Delphi... I've to interact with a SOAP service that implements WSS security with X.509 certificate so:

    • they give me the WSDL file 
    • they give me a Java Keystore (jks file) containg a certificate, a public key and a private key password protected
    • the SOAP request must be signed and crypted with the jks data
    • the SOAP response must be decrypted and signed verified

     

    a request like this one:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:fut="....." xmlns:ass="...." xmlns:com="....">
       <soapenv:Header/>
       <soapenv:Body>
          <fut:FutureConvocationsRequest>
             <associativeServicesGenericRequest>
                <ass:locale>
                   <com:language>it</com:language>
                	<com:country>IT</com:country>
                </ass:locale>
                <ass:consumer>Me</ass:consumer>
                <ass:associationCode>aaaa</ass:associationCode>
                <ass:sectionCode>bbbbb</ass:sectionCode>
                <ass:startDate></ass:startDate>
                <ass:endDate></ass:endDate>
             </associativeServicesGenericRequest>
          </fut:FutureConvocationsRequest>
       </soapenv:Body>
    </soapenv:Envelope>

     

    must become like this one (grabbed it from SoapUI logs that interact well with this service):

    <soapenv:Envelope xmlns:ass="..." xmlns:com="..." xmlns:fut="..." xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
       <soapenv:Header>
          <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
             <xenc:EncryptedKey Id="EK-6085B5AE3B1746C574167481306190992" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
                <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                   <wsse:SecurityTokenReference>
                      <ds:X509Data>
                         <ds:X509IssuerSerial>
                            <ds:X509IssuerName>....</ds:X509IssuerName>
                            <ds:X509SerialNumber>....</ds:X509SerialNumber>
                         </ds:X509IssuerSerial>
                      </ds:X509Data>
                   </wsse:SecurityTokenReference>
                </ds:KeyInfo>
                <xenc:CipherData>
                   <xenc:CipherValue>....</xenc:CipherValue>
                </xenc:CipherData>
                <xenc:ReferenceList>
                   <xenc:DataReference URI="#ED-6085B5AE3B1746C574167481306190993"/>
                </xenc:ReferenceList>
             </xenc:EncryptedKey>
             <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509-6085B5AE3B1746C574167481306190587">....</wsse:BinarySecurityToken>
             <wsu:Timestamp wsu:Id="TS-6085B5AE3B1746C574167481306190486">
                <wsu:Created>2023-01-27T09:51:01Z</wsu:Created>
                <wsu:Expires>2023-01-27T09:56:01Z</wsu:Expires>
             </wsu:Timestamp>
             <ds:Signature Id="SIG-6085B5AE3B1746C574167481306190591" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <ds:SignedInfo>
                   <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                      <ec:InclusiveNamespaces PrefixList="ass com fut soapenv" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                   </ds:CanonicalizationMethod>
                   <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
                   <ds:Reference URI="#id-6085B5AE3B1746C574167481306190590">
                      <ds:Transforms>
                         <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                            <ec:InclusiveNamespaces PrefixList="ass com fut" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                         </ds:Transform>
                      </ds:Transforms>
                      <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                      <ds:DigestValue>7APwAAzaHndcDEHSBYlA6b/rihY=</ds:DigestValue>
                   </ds:Reference>
                </ds:SignedInfo>
                <ds:SignatureValue>....</ds:SignatureValue>
                <ds:KeyInfo Id="KI-6085B5AE3B1746C574167481306190588">
                   <wsse:SecurityTokenReference wsu:Id="STR-6085B5AE3B1746C574167481306190589">
                      <wsse:Reference URI="#X509-6085B5AE3B1746C574167481306190587" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
                   </wsse:SecurityTokenReference>
                </ds:KeyInfo>
             </ds:Signature>
          </wsse:Security>
       </soapenv:Header>
       <soapenv:Body wsu:Id="id-6085B5AE3B1746C574167481306190590" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
          <xenc:EncryptedData Id="ED-6085B5AE3B1746C574167481306190993" Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
             <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
             <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <wsse:SecurityTokenReference wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd">
                   <wsse:Reference URI="#EK-6085B5AE3B1746C574167481306190992"/>
                </wsse:SecurityTokenReference>
             </ds:KeyInfo>
             <xenc:CipherData>
                <xenc:CipherValue>....</xenc:CipherValue>
             </xenc:CipherData>
          </xenc:EncryptedData>
       </soapenv:Body>
    </soapenv:Envelope>

     

    I've used several SOAP service but never with this kind of security so til now I've always used default THTTPRio with WSDL importer. I don't know if in this case this is the best approach but I've imported the WSDL file in Delphi creating all SOAP objects to use with THTTPRIO . Then I've coded the THTTPRio.OnBeforeExecute to inject the necessary data and trasform the request as needed. I've a regular license of SecureBlackBox components so I can easily read the certificate data from Keystore and using the SOAPSigner + XMLEncryptor components (with some post processing to adjust some Secureblackbox issues), I'm capable to transform the request as needed but when I send it to the service I got always an error like "The signature or decryption was invalid" (Unfortunately I can't get quick answers from the service provider because it is a government agency and not very responsive...). I suppose that could be an encryption problem because the XML soap request just signed (not encrypted) seems ok (just tested with SecureBlackbox SOAPVerifier).

     

    If there is here some SOAP Delphi guru my questions are:

    - do you know if exists a good tool to verify if the request is well formed? If the encryption is well done? If the sign is correct?

    - SecureBlackBox suite is very complex to configure... do you know if exists some other Delphi solution to obtain the result easier?

     


  7. 2 hours ago, programmerdelphi2k said:

    procedure TForm1.Button1Click(Sender: TObject);
    var
      x: TMyThread;
    begin
      x := TMyThread.Create;
      try
        // x.Start; // if suspended...
      finally
        x.Free;
      end;
    end;

    You can't destroy the thread object until it's finished... It doesn't even have time to start.

     

    Maybe you have to do something like this:

     

    var
      x: TMyThread;
    begin
      x := TMyThread.Create(False);
      try
        // x.Start; // if suspended...
        WaitForSingleObject(X.Handle, INFINITE);
      finally
        x.Free;
      end;
    end;

     

     

     

    • Like 3
    • Thanks 1

  8. I used JSON superobject for a while and it's good but in cases like this I prefer the very good Delphi NEON library so I could deserialize the JSON directly to Delphi objects. With NEON in a case like yours I could do something like this:
     

    Type
      TVoice = record
      public
        Engine : String;
        VoiceId : String;
        VoiceGender : String;
        // .. other fields 
      end;
    
      TVoicesData = record
      public
        voices_list : TArray<TVoice>;
        count : Integer;
      end;
    
      TVoices = record
      public
        success : Boolean;
        data : TVoicesData;
      end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      var sJson:=
      '{'+
      '  "success": true,'+
      '  "data": {'+
      '      "voices_list": ['+
      '          {'+
      '              "Engine": "neural",'+
      '              "VoiceId": "ai2-Stacy",'+
      '              "VoiceGender": "Female",'+
      '              "VoiceWebname": "Stacy",'+
      '              "Country": "US",'+
      '              "Language": "en-US",'+
      '              "LanguageName": "English, US",'+
      '              "VoiceEffects": ['+
      '              ]'+
      '          },'+
      '          {'+
      '              "Engine": "neural",'+
      '              "VoiceId": "ai1-Matthew",'+
      '              "VoiceGender": "Male",'+
      '              "VoiceWebname": "Matthew",'+
      '              "Country": "US",'+
      '              "Language": "en-US",'+
      '              "LanguageName": "English, US",'+
      '              "VoiceEffects": ['+
      '                  "news"'+
      '              ]'+
      '          }'+
      '      ],'+
      '      "count": 50'+
      '  }'+
      '}';
    
      var Voices:=DeserializeValueTo<TVoices>(sJson);
      for var Voice in Voices.data.voices_list do
          ListBox1.Items.Add(Voice.Engine+' - '+Voice.VoiceGender);
    
    end;
    
    function TForm1.DeserializeValueTo<T>(const aJSON : String): T;
    begin
      if FNeonConfig=Nil then FNeonConfig:=TNeonConfiguration.Default;
      var LJSON := TJSONObject.ParseJSONValue(aJSON);
      try
        var LReader:=TNeonDeserializerJSON.Create(FNeonConfig);
        try
          var LValue:=LReader.JSONToTValue(LJSON, TRttiUtils.Context.GetType(TypeInfo(T)));
          Result:=LValue.AsType<T>;
        finally
          LReader.Free;
        end;
      finally
        LJSON.Free;
      end;
    end;

     

    • Like 2

  9. In my case 10.4 was terrible, fortunately 11.2 seems working well (I'm using only VCL win32 & win64).

     

    At the moment, I've not installed the patch 1.0 because after several years of frustration I've finally a stable environment and I'm terrified of breaking it again!


  10. 13 minutes ago, balabuev said:

    I cannot agree with that. Moreover, 10.4 has a way to disable LSP in favor of old code insight engine.

    LSP is the minor problem of 10.4, you can also disable it if you want. The fact of closing the IDE every 15 minutes, in my case, is due to the continuous internal errors, access violations in dcc32 and so on that were fixed in 11.2.


  11. As far as my usage context is concerned, version 11.2 is a big step up from 10.4. I'm switching from one to the other working on two different projects and 10.4 is truly absolute crap in terms of stability. 11.2 isn't perfect but it has improved a lot of things. In my case when LSP no longer works, now in 11.2 it is always a solution to switch from debug / release or from win32 / win64 (for me these workarounds don't work in 10.4 and the only solution remain close/reopen IDE).

     

    I've been using 11.2 for several weeks now and the IDE has crashed only a couple of times (a strange Access Violation and one internal error). For me it is a dream to be able to work even for 4 hours straight without crashing! When I come back to 10.4 I have to close and reopen the IDE at least once every 15 minutes and the LSP is totally unusable...


  12. 2 minutes ago, David Heffernan said:

    I though we were talking about the cause of the access violations in your code. But if I've misunderstood, I'm sorry. 

    No problem!

     

    Discover the cause of the acces violation could be maybe a good exercise for some Windows api guru. I've dedicated it some hours yesterday trying to change the way to declare the parameters of the api but I could not reach a solution. I've tried several combinations even going against what is stated in the api documentation. There is something strange tha I'm missing on that api because the totalentries out parameter is always a non sense value called in win64. In win32 works as apected. So maybe there is something not documented in the Windows api or maybe, as that api si considered very old, maybe the win64 part could be buggy (just a my guess) or maybe could be something wrong using it from a Delphi win64 program (I've tested it both 10.4.2 and 11.2 but the problem is the same).


  13. 2 hours ago, David Heffernan said:

    Perhaps somebody else wants to debug your large and complex code. But if you made a minimal reproduction and posted it here I'd expect a better chance of engagement. 

    I know that my english is terrible but I suppose you have misunderstood the reason of this topic. I'm not looking for someone to debug my super beatiful large and complex code written in the better way possible and bla bla... As I wrote, I've already solved the problem with the workaround that I have posted (it's not the best solution but it works) and now with @Lars Fosdal kind answers I also could try other modern ways to reach my goal (like AD apis).

     

    I wrote this topic if could help somebody having the same issue. If this kind of topics are not accepted here I'll be careful not to do it again. Sorry


  14. 3 hours ago, David Heffernan said:

    ResumeHandle should be PDWORD_PTR. Probably other types are declared incorrectly. Check all declarations against the header files. 

     

    Ask yourself which is more likely. Is it a bug in your code, or a bug in the Windows code? 

    1. The code I posted is not my code. I took that example on stackoverflow here: https://stackoverflow.com/questions/34870232/list-all-users-of-an-ad-group-in-delphi. I post it just to provide a quick example that leads to the same error that I'm eperiencing (that's the reason why I posted the zip file with the project ready to test...). My code is more complex (I need more information about that api so I used anoother data structure). In my project I'm using JclWin32 to call that api and there the function is declared like this:
      function NetGroupGetUsers(servername, groupname: LPCWSTR; level: DWORD; var bufptr: PByte; prefmaxlen: DWORD; entriesread, totalentries: LPDWORD; ResumeHandle: PDWORD_PTR: NET_API_STATUS;
      The result is the same.
       
    2. Are you so sure that Windows is bug free? My code run smootlhy for at least a couple of years on a Windows 2019 server with hundreds of domain users. On that server were locked the Windows updates for a while because one of them created problems accessing via RDP. Last week we unlock the updates and boom! That piece of code now raises the access violation for which we are discussing. Sure it could be a coincidence.
       
    3. According to Microsoft documentation the declaration of that api is this one (see more at https://learn.microsoft.com/en-us/windows/win32/api/lmaccess/nf-lmaccess-netgroupgetusers)
      NET_API_STATUS NET_API_FUNCTION NetGroupGetUsers(
        [in]      LPCWSTR    servername,
        [in]      LPCWSTR    groupname,
        [in]      DWORD      level,
        [out]     LPBYTE     *bufptr,
        [in]      DWORD      prefmaxlen,
        [out]     LPDWORD    entriesread,
        [out]     LPDWORD    totalentries,
        [in, out] PDWORD_PTR ResumeHandle
      );
      and JclWin32 declaration seems correct but compiling it Win64 raises that AV.
      So it's a bug of JclWin32 code or a bug in Windows? I dont know

     


  15. 12 minutes ago, Lars Fosdal said:

    The 64-bit simply refuses to run, unless I run it elevated.

    Then I get

    Yes I'm working as admin so I can run without elevation. I suppose you have several users in the domain so it need to call the api more than one time and on second call you get AV. It is the problem for which I started this topic. If you use the MAX_PREFERED_LENGHT version (comment/uncomment instructions)  does it work? For me yes and some weeks ago worked also the original version..


  16. 3 hours ago, Lars Fosdal said:

    Windows 10, 64-bit

    Compile to 32-bit target - runs as expected

    Compile to 64-bit target - unable to create process

    I'm compiling it both 32bit and 64bit and they work both here.

    I'm on Windows 10 64bit with Delphi 11.2.

     

    The 64bit compiled exe I've tested also on Win11 (22H1) and on WinServer 2019 and Winserver 2022 and it works everywhere.

     

     


  17. 3 hours ago, David Heffernan said:

    Would be nice to look at code directly in the post rather than have to download some ZIP file

    {$WARN SYMBOL_PLATFORM OFF}
    
    program DomainGroupGetUsersTest;
    
    {$APPTYPE CONSOLE}
    
    uses
      SysUtils, Windows, Classes;
    
    const
        netapi32lib = 'netapi32.dll';
    
    type
        PGroupUsersInfo0 = ^TGroupUsersInfo0;
        _GROUP_USERS_INFO_0 = record
          grui0_name: LPWSTR;
        end;
        TGroupUsersInfo0 = _GROUP_USERS_INFO_0;
        GROUP_USERS_INFO_0 = _GROUP_USERS_INFO_0;
    
        NET_API_STATUS = DWORD;
        LPBYTE = ^BYTE;
    
    function NetApiBufferFree (Buffer: Pointer): NET_API_STATUS; stdcall;
                                                               external netapi32lib;
    function NetGroupGetUsers (servername: LPCWSTR; groupname: LPCWSTR;
        level: DWORD; var bufptr: LPBYTE; prefmaxlen: DWORD; var entriesread: DWORD;
        var totalentries: DWORD; ResumeHandle: PDWORD): NET_API_STATUS; stdcall;
                                                               external netapi32lib;
    
    function DomainGroupGetUsers (const sGroup: WideString;
                                  const UserList: TStrings;
                                  const sLogonServer: WideString) : Boolean;
    { "sLogonServer" must be prefixed with "\\".
      "sGroup" must contain the group name only. }
    
    type
        TaUserGroup = array of TGroupUsersInfo0;
    
    const
        PREF_LEN = 1024;
    //    MAX_PREFERRED_LENGTH = DWORD(-1);
    
    var
        pBuffer : LPBYTE;
        i : Integer;
        Res : NET_API_STATUS;
        dwRead, dwTotal, hRes : DWord;
    
    begin
        Assert (sGroup <> '');
        Assert (sLogonServer <> '');
        Assert (UserList <> NIL);
    
        UserList.Clear;
        Result := true;
        hRes := 0;
    
        repeat
            writeln('hres = '+IntToStr(hRes));
    
    //        Res := NetGroupGetUsers (PWideChar (sLogonServer), PWideChar (sGroup),
    //                                 0, pBuffer, MAX_PREFERRED_LENGTH, dwRead, dwTotal,
    //                                 PDWord (@hRes));
            Res := NetGroupGetUsers (PWideChar (sLogonServer), PWideChar (sGroup),
                                     0, pBuffer, PREF_LEN, dwRead, dwTotal,
                                     PDWord (@hRes));
    
    
            writeln('dwRead = '+IntToStr(dwRead));
            writeln('dwTotal = '+IntToStr(dwTotal));
    
            if (Res = Error_Success) or (Res = ERROR_MORE_DATA) then
            begin
                if (dwRead > 0) then
                    for i := 0 to dwRead - 1 do
                        with TaUserGroup (pBuffer) [i] do
                            UserList.Add (grui0_name);
    
                NetApiBufferFree (pBuffer);
            end { if }
            else Result := false;
        until (Res <> ERROR_MORE_DATA);
    end; { DomainGroupGetUsers }
    
    
    var
        UserList : TStringList;
        iIndex : Integer;
    
    begin
        UserList := TStringList.Create;
    
        try
            DomainGroupGetUsers ('Domain Users', UserList,
                                 GetEnvironmentVariable ('LOGONSERVER'));
    
            for iIndex := 0 to UserList.Count - 1 do
                WriteLn (UserList [iIndex]);
    
        finally
            UserList.Free;
        end; { try / finally }
    
        if (DebugHook <> 0) then
        begin
            WriteLn;
            Write ('Press [Enter] to continue ...');
            ReadLn;
        end; { if }
    end.

     


  18. Hi all, this is not directly Delphi related, just want to share if anyone will experience something like this.

     

    I'm using NetGroupGetUser api (from netapi32.dll) to retrive names and data of the domain users. It worked well for a while, but now (maybe some recent Windows Updates), in win64 applications, it returns me strange results or access violations. Same code compiled in Win32 instead always worked fine. Attached is a sample that I've found online (stackoverflow) that I'm using to do some tests. The original program was designed to retrieve data in buffers (1024byte). Doing that, in my case, if users number exceeds the buffer, the second call of NetGroupGetUser raise an access violation in samlib.dll (running on a Windows 2019 server). I've solved calling the api once using MAX_PREFERRED_LENGTH (=DWORD(-1)) instead of the original 1024 byte buffer size. I could not find documentation about differences in declaring the api for win32 or win64... It seems some kind of mess with the api parameters in 64 bit or a bug of 64bit version of netapi32.dll.

    TestDomainUserConsole.zip

×