Jump to content

Mark-

Members
  • Content Count

    303
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by Mark-


  1. 17 minutes ago, Angus Robertson said:

    I've tested the FtpUpOneFile function against my FTP server, and it works are expected.

    Thanks for your help Angus.

     

    I spent all day and some night, testing and I am confident the host has done some shenanigans to stop supporting "exe" files.

    I tested against https://sftpcloud.io/tools/free-ftp-server and it failed due to not supporting the rename function.

     

    Stepping though code, "RemTarFile not being passed to the function, " is without a doubt being correctly passed.

     

    For now, because I needed a working solution, I went back to an old version of the program what uses TFtpClient, altered it to:

    Delete the file to be replaced on the server.

    Set the new file name to .zip.

    Transfer the file.

    Rename the file to exe.

    That works.

     

    I know that is basically what the multi component did. I suspect the "zip" extension, a "supported" file type, is ignored as a potential threat. And perhaps the lack of a file extension for the temporary file name, of uploading the file, was an issue. Speculation.

     

    Now, I will be looking at switching to using 7zip to wrap the installer.exe in a self extracting archive. That should handle the "exe" support issue for the current host and future host.

     


  2. Thanks Angus.

    Yeah the hosting company support is giving me nothing. "We don't support exe". But, for more than a decade it has not been an issue. When did it change? Answer: Crickets.

     

    Our 25 MB pdf file upload also fails.

    Uploading with FileZilla works. It does time out at the end, on occasion, but the file is uploaded.

     

    I will be testing with https://sftpcloud.io/tools/free-ftp-server, RebexTinyFtpServer and FileZilla_Server_1.8.2, soon.

    As well as seeking a new host. 🙂

     

    I might have to switch to zipping the installer. It will cause some issues that will need sorting.

     


  3. Thanks for the response.

     

    Yes, the file name is passed in "RemTarFile".

     

    function TIcsFtpMulti.FtpUpOneFile (const LocFileFull, RemTarDir, RemTarFile: string; Replopt: TIcsFileCopyRepl) : TIcsTaskResult ;

     

    > the file name a few times already. 

     

    It does.

     

    This has been working for years. I wonder if something server side has changed.

     

    Very interesting. More testing.

     

     

     

     


  4. Thanks.

    I ran the OverbyteIcsXferTst sample, using the SingltFTP tab and here is the end of the transfer.

     

    08:47:35:099 08:47:35:099 DataSocketPutDataSent 47864
    08:47:35:376 08:47:35:376 DataSocketPutDataSent 0
    08:47:35:376 08:47:35:376 024E0A60 TCustomWSocket.Shutdown 1 handle=1260
    08:47:37:443 08:47:37:443 ! Data Session closed
    08:47:37:443 08:47:37:443 024E0A60 SocketCloseCalled handle=1260
    08:47:37:443 08:47:37:443 024E0A60 TCustomWSocket.Shutdown 1 handle=1260
    08:47:37:449 < 226 Transfer complete
    08:47:37:449 ! 81.7Mbytes received/sent in 279 seconds (300Kbytes/sec)
    08:47:37:650 Uploaded File 
    08:47:37:650 08:47:37:650 Start command, Req=MlstAsync - MLST filetest_exe
    08:47:37:650 > MLST filetest_exe
    08:47:37:844 <  modify=20240821134736;perm=adfrw;size=85703416;type=file;unique=10004AU3E699E12;UNIX.group=15000;UNIX.groupname=www;UNIX.mode=0644;UNIX.owner=454709;UNIX.ownername=<me>; /public_html/releases/filetest_exe
    08:47:37:844 < 250 End of list
    08:47:37:844 08:47:37:844 Start command, Req=DeleAsync - DELE 
    08:47:37:844 > DELE 
    08:47:37:921 < 501 Invalid number of parameters
    08:47:37:921 08:47:37:921 Start command, Req=RenFromAsync - RNFR filetest_exe
    08:47:37:921 > RNFR filetest_exe
    08:47:37:992 < 350 File or directory exists, ready for destination name
    08:47:37:992 08:47:37:992 Start command, Req=RenToAsync - RNTO 
    08:47:37:992 > RNTO 
    08:47:38:059 < 501 Invalid number of parameters
    08:47:38:059 Final Rename Failed from: filetest_exe to 
    08:47:38:059 Upload Failed: 501 Invalid number of parameters

     


  5. Thanks for the response.

     

    > Can you please email me the normal log of the complete session, showing all commands and files. 

     

    I do not see any logging options other than TIcsLogger. Do I need to create logging with OnCommand, OnResponse, etc.?

    I am not using SSL/TLS.

    The file is about 95 MB.

     

    Yeah I have thought about upgrading but, I use other ICS components, extensively, and it would take a good bit of testing. Might need to do it.

     

    Thanks for all your work on ICS.

     

     

     


  6. Hello,

     

    Delphi 10.2

     

    I have been using TIcsFtpMulti.FtpUpOneFile for long time without issue.

    In the last month of so it started failing, no changes on this end.

    A TIcsLogger was set up and this is the end portion of the transfer.

     

    14:14:49:951 07261C40 PutDataInSendBuffer handle=1332  len 65536 [1492]
    14:14:49:951 07261C40 TryToSend handle=1332
    14:14:49:998 07261C40 TryToSend handle=1332
    14:14:50:029 07261C40 TryToSend handle=1332
    14:14:50:029 07261C40 TryToSend handle=1332
    14:14:50:045 07261C40 TryToSend handle=1332
    14:14:50:201 07261C40 TryToSend handle=1332
    14:14:50:201 07261C40 TriggerDataSent handle=1332
    14:14:50:201 DataSocketPutDataSent 47272
    14:14:50:201 07261C40 PutDataInSendBuffer handle=1332  len 47272 [1493]
    14:14:50:201 07261C40 TryToSend handle=1332
    14:14:50:201 07261C40 TryToSend handle=1332
    14:14:50:295 07261C40 TryToSend handle=1332
    14:14:50:295 07261C40 TryToSend handle=1332
    14:14:50:373 07261C40 TryToSend handle=1332
    14:14:50:373 07261C40 TryToSend handle=1332
    14:14:50:467 07261C40 TryToSend handle=1332
    14:14:50:467 07261C40 TryToSend handle=1332
    14:14:50:467 07261C40 TriggerDataSent handle=1332
    14:14:50:467 DataSocketPutDataSent 0
    14:14:50:467 07261C40 TCustomWSocket.Shutdown 1 handle=1332
    14:14:50:795 ! Data Session closed                                      <------------------Does this mean the server closed the session, or is this an "internal" TIcsFtpMulti session?
    14:14:50:795 ! Next3PutAsync
    14:14:50:795 07261C40 SocketCloseCalled handle=1332
    14:14:50:795 07261C40 TCustomWSocket.Shutdown 1 handle=1332
    14:15:05:481 ! Aborting
    14:15:05:481 Control Socket Closed, error=0
    14:15:05:481 ! HighLevelAsync 0
    14:15:05:481 ! Abort detected
    14:15:05:481 ! HighLevelAsync done

     

    If I read correctly. the server is aborting the connection after the complete file is sent.

    Looking at the server contents the file is there with the transferred file name and if I read this right, the next step would be, delete the old file and rename the transferred file to the correct name.

     

    If the old file does not exist, it still fails.

     

    Ideas?

     

    Thanks,

     

    Mark

     


  7. 19 minutes ago, Fred Ahrens said:

    The e-mail that you received from MS is related to your Azure account, not to code signing. The e-mail should also contain links to the place where you can enable MFA.

    Yeah that is what I thought but, no links lead to it. Most links lead to documentation.

    The one link that gets you to:

    image.png.fefc8c72d725775e009de609aba01dde.png

     

    Selecting Multifactor authentication takes you to:

     

    image.thumb.png.46605b0563fa039ed4a3fd6cac70e20c.png

     

    "Get Free Premium Trial":

    image.thumb.png.f9be0721437d2e3877b27d93968093f0.png

     

    Confused.

    15 minutes ago, dummzeuch said:

    Which in itself could be a phishing attempt. Just saying.

    That was might first thought. So I checked it out and it is legit.


     

     

     


  8. On 5/31/2024 at 8:57 AM, Mark- said:

    Thanks. Yeah, time of day might have a big impact.

    Just a follow up and a new question.

    The time can be a couple of seconds or 191 seconds. When the automated build runs it signs about 20 files. All 20 are 2-4 seconds or all are 191 seconds. Go figure.

     

    On another note, I received an email "Action required: Enable multifactor authentication for your tenant by 15 October 2024"

     

    We are paying a monthly fee for the code signing service and everywhere I searched the system wants me to sign up for some other "premium" service. I have not found a location to active MFA for the code signing service.

     

    Any ideas?

     


  9. 4 minutes ago, Fred Ahrens said:

    On our systems it takes between 2 to 4 seconds per file. Hard to say what might have an influence on this duration. 

    It may depend on the region where your signing account is located. We use West Europe.

    Internet speed could also be an important variable in this game.

    Thanks. Yeah, time of day might have a big impact.


  10. > Have you set the environment variables AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET?

     

    Yes.

     

    I do not have the last one "App". Went back over the step #5 instruction (https://melatonin.dev/blog/code-signing-on-windows-with-azure-trusted-signing/#step-4-create-an-app-registration) and now have a "Trusted Signing Certificate Profile Signer" with "App" as the type.

    And drum roll.

     

    Submitting digest for signing...
    
    OperationId xxxx: InProgress
    
    Signing completed with status 'Succeeded' in 192.2221622s
    
    Successfully signed: C:\apptest.exe
    
    Number of files successfully Signed: 1
    Number of warnings: 0
    Number of errors: 0

    Thank you very much Fred Ahrens.

    Thank you Sudara for your blog post.


  11. 4 minutes ago, Fred Ahrens said:

    Are the values shown for "CodeSigningAccountName" and "CertificateProfileName" correct? If yes, those values should be redacted in your post. If not, you need to update your metadata file.

    I changed them for the post.

    The actual ones are correct, as far as I know.

    The "CodeSigningAccountName"  from here:

     

    image.png.59e36dac57697f449ff8e6e0ba04bd4b.png

     

    "CertificateProfileName" from here:

     

    image.png.78005ad958d53a9f1ca269f1f1fcc377.png


  12. 5 hours ago, Fred Ahrens said:

    The client secret of the app is the "Value" entry in section "Certificates & secrets" - not "Secret ID" (it's visible only for a short time; if it's no longer visible and you don't know the value, you'll need to create a new client secret). BTW: That's also the first place to check if the signing suddenly stops working. Usually it's caused by an expired client secret.

    Thank you.

     

    I recreated the client secret and the error changed. 🙂

    Not sure what it means. Perhaps Azure is having a problem at the moment?

     

    Trusted Signing
    
    Version: 1.0.59
    
    "Metadata": {
      "Endpoint": "https://eus.codesigning.azure.net/",
      "CodeSigningAccountName": "NameZ",
      "CertificateProfileName": "ProfileZ",
      "ExcludeCredentials": []
    }
    
    Submitting digest for signing...
    Unhandled managed exception
    Azure.RequestFailedException: Service request failed.
    Status: 403 (Forbidden)
    
    Headers:
    Date: Fri, 31 May 2024 12:15:50 GMT
    Connection: keep-alive
    Strict-Transport-Security: REDACTED
    x-azure-ref: REDACTED
    X-Cache: REDACTED
    Content-Length: 0
    
       at Azure.CodeSigning.CertificateProfileRestClient.SignAsync(String codeSigningAccountName, String certificateProfileName, SignRequest body, String xCorrelationId, String clientVersion, CancellationToken cancellationToken)
       at Azure.CodeSigning.CertificateProfileClient.StartSignAsync(String codeSigningAccountName, String certificateProfileName, SignRequest body, String xCorrelationId, String clientVersion, CancellationToken cancellationToken)
       at Azure.CodeSigning.Dlib.Core.DigestSigner.SignAsync(UInt32 algorithm, Byte[] digest, SafeFileHandle safeFileHandle, CancellationToken cancellationToken)
       at Azure.CodeSigning.Dlib.Core.DigestSigner.Sign(UInt32 algorithm, Byte[] digest, SafeFileHandle safeFileHandle)
       at AuthenticodeDigestSignExWithFileHandleManaged(_CRYPTOAPI_BLOB* pMetadataBlob, UInt32 digestAlgId, Byte* pbToBeSignedDigest, UInt32 cbToBeSignedDigest, Void* hFile, _CRYPTOAPI_BLOB* pSignedDigest, _CERT_CONTEXT** ppSignerCert, Void* hCertChainStore)
    
    SignTool Error: An unexpected internal error has occurred.
    Error information: "Error: SignerSign() failed." (-2147467259/0x80004005)

     


  13. 1 hour ago, Fred Ahrens said:

    It looks like you did exclude all available authentication methods via "ExcludeCredentials". If you leave this parameter empty and provide authentication details via environment variables, you should be able to use your certificate.

     

    As long as the authentication doesn't work, you may get a lot of misleading error messages - like "Azure CLI not installed". Actually, Azure CLI is not needed at all. Without authentication SignTool will also not be able to find a valid certificate.

     

    I should mention: I assume you try to set up a simple batch file that does the code signing for you. If not, let me know your planned code signing process.

    Thanks for the response.

     

    I added the "ExcludeCredentials" after it did not work when I read on SO someone say adding them worked from them.

    Yes, I am using a batch file.

    Where I am getting the "CodeSigningAccountName" is the correct location?

     

    I removed the "ExcludeCredentials" from the json file and ran it again. Took awhile to complete. The results are much different, same error code: SignerSign() failed." (-2147467259/0x80004005)

     

    I see this: "Original exception: AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID,..."

     

    Sticks out. I know the secret is correct and it appears it can not be changed in Azure. I assume I will need to generate another cert? Or look for...?

     

     


  14. OK, got it to at least try and sign the exe.

    Still not sure about " CodeSigningAccountName"

    Trusted Signing
    
    Version: 1.0.59
    
    "Metadata": {
      "Endpoint": "https://eus.codesigning.azure.net/",
      "CodeSigningAccountName": "TheName",
      "CertificateProfileName": "TheCert",
      "ExcludeCredentials": [
        "ManagedIdentityCredential",
        "EnvironmentCredential",
        "WorkloadIdentityCredential",
        "SharedTokenCacheCredential",
        "VisualStudioCredential",
        "VisualStudioCodeCredential",
        "AzurePowerShellCredential",
        "AzureDeveloperCliCredential",
        "InteractiveBrowserCredential"
      ]
    }
    
    Submitting digest for signing...
    Unhandled managed exception
    Azure.Identity.CredentialUnavailableException: Azure CLI not installed
       at Azure.Identity.DefaultAzureCredential.GetTokenFromSourcesAsync(TokenCredential[] sources, TokenRequestContext requestContext, Boolean async, CancellationToken cancellationToken)
       at Azure.Identity.DefaultAzureCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
       at Azure.Identity.CredentialDiagnosticScope.FailWrapAndThrow(Exception ex, String additionalMessage, Boolean isCredentialUnavailable)
       at Azure.Identity.DefaultAzureCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
       at Azure.Identity.DefaultAzureCredential.GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
       at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.GetHeaderValueFromCredentialAsync(TokenRequestContext context, Boolean async, CancellationToken cancellationToken)
       at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.GetHeaderValueAsync(HttpMessage message, TokenRequestContext context, Boolean async)
       at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.GetHeaderValueAsync(HttpMessage message, TokenRequestContext context, Boolean async)
       at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AuthenticateAndAuthorizeRequestAsync(HttpMessage message, TokenRequestContext context)
       at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
       at Azure.Core.Pipeline.RedirectPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
       at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
       at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
       at Azure.CodeSigning.CertificateProfileRestClient.SignAsync(String codeSigningAccountName, String certificateProfileName, SignRequest body, String xCorrelationId, String clientVersion, CancellationToken cancellationToken)
       at Azure.CodeSigning.CertificateProfileClient.StartSignAsync(String codeSigningAccountName, String certificateProfileName, SignRequest body, String xCorrelationId, String clientVersion, CancellationToken cancellationToken)
       at Azure.CodeSigning.Dlib.Core.DigestSigner.SignAsync(UInt32 algorithm, Byte[] digest, SafeFileHandle safeFileHandle, CancellationToken cancellationToken)
       at Azure.CodeSigning.Dlib.Core.DigestSigner.Sign(UInt32 algorithm, Byte[] digest, SafeFileHandle safeFileHandle)
       at AuthenticodeDigestSignExWithFileHandleManaged(_CRYPTOAPI_BLOB* pMetadataBlob, UInt32 digestAlgId, Byte* pbToBeSignedDigest, UInt32 cbToBeSignedDigest, Void* hFile, _CRYPTOAPI_BLOB* pSignedDigest, _CERT_CONTEXT** ppSignerCert, Void* hCertChainStore)
    
    SignTool Error: An unexpected internal error has occurred.
    Error information: "Error: SignerSign() failed." (-2147467259/0x80004005)

    And this:

    Azure.Identity.CredentialUnavailableException: Azure CLI not installed

    "not installed"?


  15. On 5/3/2024 at 10:21 AM, Fred Ahrens said:

    Then you need to create the metadata.json file to be used with SignTool and the Azure Trusted Signing DLL:

    
    {
      "Endpoint": "correct URL for your area",
      "CertificateProfileName": "name of the certificate in your trusted signing account",
      "CodeSigningAccountName": "name of your Trusted Signing account, NOT your e-mail address or other user ID"
     }

     

    Hello,

     

    Thought I had it all set up but no joy so looking at everything, get this:

     

    The following certificates were considered:
    After EKU filter, 0 certs were left.
    After expiry filter, 0 certs were left.
    SignTool Error: No certificates were found that met all the given criteria.

     

    "CodeSigningAccountName"

     

    The name under the green:

     

    image.png.6f65e951b25c5ac40e4afce5b8dd664e.png

     

    Thanks,

     

    Mark

     


  16. 1 minute ago, Brandon Staggs said:

    ...but you may get faster results asking a chat AI to convert it for you.

    I did that a few days ago out of curiosity. I did it a function at a time so it needs work to make it workable.

    procedure FindDesktopFolderView(riid: TGUID; var ppv: Pointer);
    var
      spShellWindows: IShellWindows;
      vtLoc: OleVariant;
      vtEmpty: OleVariant;
      lhwnd: LongInt;
      spdisp: IDispatch;
      spBrowser: IShellBrowser;
      spView: IShellView;
    begin
      spShellWindows := CoShellWindows.Create;
      vtLoc := CSIDL_DESKTOP;
      vtEmpty := VarEmpty;
      spShellWindows.FindWindowSW(vtLoc, vtEmpty, SWC_DESKTOP, lhwnd, SWFO_NEEDDISPATCH, spdisp);
      spBrowser := (spdisp as IServiceProvider).QueryService(SID_STopLevelBrowser, IShellBrowser) as IShellBrowser;
      spBrowser.QueryActiveShellView(spView);
      spView.QueryInterface(riid, ppv);
    end;
    
    -----------------
    
    program DesktopFolderView;
    
    {$APPTYPE CONSOLE}
    {$R *.res}
    
    uses
      System.SysUtils,
      ActiveX,
      ComObj,
      ShlObj,
      ShellAPI;
    
    // CCoInitialize incorporated by reference
    
    function wmain(argc: Integer; argv: PWideChar): Integer;
    var
      init: IUnknown; // Equivalent to CCoInitialize
      spView: IFolderView;
      spFolder: IShellFolder;
      spEnum: IEnumIDList;
      spidl: PItemIDList;
      str: TStrRet;
      spszName: PWideChar;
      pt: TPoint;
    begin
      init := CreateComObject(CLSID_CoInitialize);
      FindDesktopFolderView(IID_IFolderView, spView);
      spView.GetFolder(IID_IShellFolder, spFolder);
    
      spView.Items(SVGIO_ALLVIEW, IID_IEnumIDList, spEnum);
      while spEnum.Next(1, spidl, nil) = S_OK do
      begin
        spFolder.GetDisplayNameOf(spidl, SHGDN_NORMAL, str);
        StrRetToStr(@str, spidl, spszName);
    
        spView.GetItemPosition(spidl, pt);
        Writeln(Format('At %4d,%4d is %s', [pt.x, pt.y, WideString(spszName)]));
        CoTaskMemFree(spidl);
      end;
      Result := 0;
    end;
    
    begin
      try
        CoInitialize(nil);
        wmain(ParamCount, PWideChar(ParamStr(0)));
        CoUninitialize;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    end.
    ---------------------------
    program DesktopFolderRandomPosition;
    
    {$APPTYPE CONSOLE}
    
    uses
      System.SysUtils,
      ActiveX,
      ComObj,
      ShlObj,
      ShellAPI,
      Windows;
    
    function wmain(argc: Integer; argv: PWideChar): Integer;
    var
      init: IUnknown; // Equivalent to CCoInitialize
      spView: IFolderView;
      spEnum: IEnumIDList;
      spidl: PItemIDList;
      pt: TPoint;
      apidl: array[0..0] of PItemIDList;
    begin
      init := CreateComObject(CLSID_CoInitialize);
      FindDesktopFolderView(IID_IFolderView, spView);
    
      spView.Items(SVGIO_ALLVIEW, IID_IEnumIDList, spEnum);
      while spEnum.Next(1, spidl, nil) = S_OK do
      begin
        spView.GetItemPosition(spidl, pt);
        pt.x := pt.x + (Random(5) - 2);
        pt.y := pt.y + (Random(5) - 2);
    
        apidl[0] := spidl;
        spView.SelectAndPositionItems(1, @apidl[0], @pt, SVSI_POSITIONITEM);
        CoTaskMemFree(spidl);
      end;
      Result := 0;
    end;
    
    begin
      try
        CoInitialize(nil);
        Randomize; // Initialize random number generator
        wmain(ParamCount, PWideChar(ParamStr(0)));
        CoUninitialize;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    end.
    ------------------------------------
    procedure SavePositions(pView: IFolderView; pszFile: PWideChar);
    var
      spStream: IStream;
      spEnum: IEnumIDList;
      spidl: PItemIDList;
      pt: TPoint;
    begin
      SHCreateStreamOnFileEx(pszFile, STGM_CREATE or STGM_WRITE,
        FILE_ATTRIBUTE_NORMAL, True, nil, spStream);
      pView.Items(SVGIO_ALLVIEW, IID_IEnumIDList, spEnum);
      while spEnum.Next(1, spidl, nil) = S_OK do
      begin
        WritePidlToStream(spStream, spidl); // Custom function to write PIDL to stream
        pView.GetItemPosition(spidl, pt);
        WritePointToStream(spStream, pt); // Custom function to write POINT to stream
        ILFree(spidl); // Free the PIDL
      end;
    end;
    
    -----------------------------------
    procedure RestorePositions(pView: IFolderView; pszFile: PWideChar);
    var
      spStream: IStream;
      spidl: PItemIDList;
      pt: TPoint;
      apidl: array[0..0] of PItemIDList;
    begin
      // Create a file stream
      SHCreateStreamOnFileEx(pszFile, STGM_READ, FILE_ATTRIBUTE_NORMAL, False, nil, spStream);
      // Read PIDLs and their positions from the stream and restore them
      while Succeeded(IStream_ReadPidl(spStream, spidl)) and
            Succeeded(spStream.Read(@pt, SizeOf(pt), nil)) do
      begin
        apidl[0] := spidl;
        pView.SelectAndPositionItems(1, @apidl[0], @pt, SVSI_POSITIONITEM);
        CoTaskMemFree(spidl); // Free the PIDL
      end;
    end;
    
    // Note: IStream_ReadPidl is a placeholder for the actual function you would use to read a PIDL from a stream.
    // You will need to implement this functionality in Delphi, as it is not provided by Delphi's standard libraries.

     

    • Like 1
×