Jump to content

Mark Williams

Members
  • Content Count

    282
  • Joined

  • Last visited

Everything posted by Mark Williams

  1. Mark Williams

    64bit Out of Process Server

    Thanks for the tip. I will look into it if I have problems via com. My out of process server is only intended for (and will only work with) a Word Add-In that I am developing. So I may run into problems with 32 bit via 64 bit if users are running 32 bit word. So that's something I'm going to have to overcome.
  2. Mark Williams

    64bit Out of Process Server

    Thanks that worked. I originally just ran my app from a shortcut with the /regserver parameter, but that didn't seem to work ie no entries in the register. Running it through the IDE with /regserver did the job. However, how do I import this type library into Delphi? As I mention above it is 64 bit and therefore you can't do it via the IDE so I have tried with tlibimp.exe via a cmd prompt. It still report an error loading the type library.
  3. Mark Williams

    TIDHTTP -v- THTTPCLient

    I have been testing TIDHttp against THTTPClient. Using a local server with TLS1 and nothing else going on but the test downloads I have found that there is little difference in speed between TIDHttp and THttpClient. I have been using THTTPClient up until now, but thought I had better check out TIDHTTP. If speed is not a reason for changing and I am otherwise happy with the THTTPClient are there any other reasons I should consider changing for?
  4. Mark Williams

    TIDHTTP -v- THTTPCLient

    The post seems to mention a fix, but I haven't tried it. I have an old Windows 7 machine here somewhere and will check it out. However, since Windows 7 is no longer supported and, presumably, no longer secure to use and my app has to be run in a secure environment, it is probably okay for me to say that Windows 7 is not supported.
  5. Mark Williams

    TIDHTTP -v- THTTPCLient

    I'm doing a lot more than polling an url, but I don't appear to be having any issues with THTTPClient and it is pretty simple to set up and use and it doesn't need OpenSSL, I personally can't see any particular reason to switch to Indy. although it would be pretty simple to do so, I was just wondering if there were any known issues/frailties with THTTPClient that would provide an imperative for switching to Indy.
  6. I am configuring my server (TWebModule) to dispense with TLS where the request is from a machine on a local network. To do this I am checking the following properties of TWebRequest: ServerPort - to see if the request has come in on 443 If not 443 then RemoteAddr - to see if the ip address of the requestee falls within the private ranges: 10.0.0.0 - 10.255.255.255 172.16.0.0 - 172.31.255.255 192.168.0.0 - 192.168.255.255 If it doesn't reject the request and ask it to be made over http. Is this a sound approach? Are there any dangers I should be aware of? If this is a sound approach I assume I should add a config files to specify the permitted ip ranges so that it could include private networks that fall out
  7. Mark Williams

    Switching TLS on/off on Server

    Researching a little more thoroughly, I've come to the conclusion that this is probably not a good idea for security reasons.
  8. Mark Williams

    Combobox Value pairs

    I don't think there is. IndexOf checks the whole item including the NameValueSeparator. Presumably you mean IndexofName. You can use ValueFromIndex to iterate through each of the items in the TStrings: for i := 0 to myList.count-1 do if myList.ValueFromIndex='myvalue' then begin //Got it break; end;
  9. Within a Delphi document management application I use COM to open MS word documents. Hyperlinks can be added to the Word document which are references to image files maintained by the Delphi application. When the user clicks on a hyperlink in Word a message is returned to the Delphi app which in turn responds by opening a form which displays the required image. Whilst I want the image form to be top of the z-rder and activated I would like to keep the Word window just below it in the z-order ie above any other open windows in the Delphi application including the main form. First I tried: ImgForm := TFrmImage.Create(Nil); ImgForm.ParentWindow := Wordwnd; ImgForm.Show; SetWindowPos(WordWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE OR SWP_NOACTIVATE); SetWindowPos(ImgForm.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE OR SWP_NOACTIVATE); This didn't work. The application main form appeared on top of the Word window. I then tried creating the image form without activating it: ImgForm := TFrmImage.Create(Nil); ImgForm.visible := false; ImgForm.ParentWindow := Wordwnd; SetWindowPos(WordWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE OR SWP_NOACTIVATE); SetWindowPos(ImgForm.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE OR SWP_NOACTIVATE); Same result!. I am using a Delphi Add-In within Word to provide additional ribbon functions etc. Somewhat tongue in cheek I tried a different approach. When the user clicks on a hyperlink the Add-In creates a new form "HostForm" and then sends a request through to the Delphi app to open ImgForm. The Delphi App does the following: ImgForm := TImgForm.Create(Nil); ImgForm.Visible := false; ImgForm.borderStyle := bsNone; ImgForm.ParentWindow := Wnd; //ie the handle of HostForm ImgForm.Align := alClient; ImgForm.Visible := true; Much to my amazement it worked. ImgForm was embedded in HostForm. HostForm was top of the Zorder with the word window below it and the Delphi app below the word window. The only thing that didn't work was the alignment. A couple of questions: Is it possible simply to align ImgForm to HostForm or will I need to deal with it in HostForm's resize event? I have noticed that if I close the Delphi app ImgForm is also closed ie it just disappears from HostForm and if I close HostForm, ImgForm remains in existence albeit it cannot be seen. These effects are I suppose to be expected and should be easily handled. But am I missing more potentially significant problems that will be more difficult or even impossible to handle?
  10. Mark Williams

    SendMessage From DLL

    I have a Word Add-In created with Add-In Express, although that's probably irrelevant. The Add-In can only be used for word docs created via a certain desktop app (MyAPP). When MyAPP creates a Word document it stores a unique identifier for that Word document and also the handle of MyAPP. I am trying to send information from the Add-In DLL back to MyApp using SendMessage and WM_COPYDATA. I have the following types declared in both the DLL and MyAPP: type TWordFunction = (wfNone, wfEdit, wfSave, wfLink, wfMasterWindow, wfBundle); type TWordActionRec = Record wf:TWordFunction; wordID:THandle; end; Within the DLL: procedure TAddInModule.DefaultButtonAction(wordFunction : TWordFunction); var WAR : TWordActionRec; copyDataStruct : TCopyDataStruct; hdl : THandle; begin hdl := GetViewerHandle; WAR.wf := WordFunction; WAR.wordID := GetWordIdentifier; copyDataStruct.dwData := 0; copyDataStruct.cbData := SizeOf(WAR); copyDataStruct.lpData := @WAR; WinAPI.Windows.SendMessage(hdl, WM_COPYDATA, 0, Integer(@copyDataStruct)); end; The above runs without triggering any error and the hdl parameter is correct for MyAPP. Within MyAPP: procedure TForm1.WMCopyData(var Msg: TWMCopyData); var WAR : TWordActionRec; begin WAR := TWordActionRec(Msg.CopyDataStruct.lpData^); ListBox1.Items.Add(WAR.wordID.ToString); Case WAR.wf of wfNone: ListBox2.Items.Add('None'); wfEdit: ListBox2.Items.Add('Edit'); wfSave: ListBox2.Items.Add('Save'); wfLink: ListBox2.Items.Add('Link'); wfMasterWindow: ListBox2.Items.Add('MW'); wfBundle: ListBox2.Items.Add('Bundle'); End; end; However, the DLL's message is never received by MyApp. If I take the code from the DDL and add it to a standard executable it works as expected. I have Googled to see if there is any reason why SendMessage would not work within a DLL and as far as I can see there shouldn't be. Is there anything wrong with my code or is this perhaps an Add-IN Express specific issue?
  11. Mark Williams

    SendMessage From DLL

    BTW should have noted there was no need for ChangeWindowMessageFilterEx, but good to know about it.
  12. Mark Williams

    SendMessage From DLL

    Ah ha! The penny at last drops. The dangers of copying code that works in 32 bit, but no longer in 64 bit. My DLL is 64bit, but when I created a test executable to try and send the message I must have compiled it as 32 bit rather than 64 so it worked. The SendMessage needed to be: WinAPI.Windows.SendMessage(Hdl, WM_COPYDATA, 0, LPARAM(@copyDataStruct)); That was the only reason the message was not getting through and had I realised this 48 hours ago I might have some hair left. It's time for that Lockdown drink! I will raise a glass to you
  13. Mark Williams

    SendMessage From DLL

    It might be a UIPI issues as flagged by @David Heffernan initially and missed by me! But I don't think so. However not dealt with UIPI issues before so I may be handling it incorrectly, Whilst Word runs at a low level I think the DLL Add-In will be at the same level as my receiving app. Also, as you pointed out if there is an UIPI error then GetLastError is set to 5. My SendMessage is reporting success. However I have tried to incorporate ChangeWindowFilterEx within my receiving app to see if that makes any difference. type TChangeFilterStruct = packed record cbSize: DWORD; ExtStatus: DWORD; end; PChangeFilterStruct = ^TChangeFilterStruct; function ChangeWindowMessageFilterEx(hWnd: HWND; Message: UINT; Action: DWORD; ChangeFilterStruct: PChangeFilterStruct): Bool; stdcall; external 'user32.dll'; const MSGFLT_ALLOW = 1; MSGFLT_DISALLOW = 2; MSGFLT_RESET = 0; {In formcreate:} ChangeWindowMessageFilterEx(Handle, WM_COPYDATA, MSGFLT_ALLOW, nil); If I am implementing this correctly there doesn't appear to be a UIPI error.
  14. Mark Williams

    SendMessage From DLL

    Word ID is a randomly generated integer value. It's not intended to be used as a handle. Just a way of identifying which Word window my app is communicating with. My app passes its own handle to be stored in the word document as follows: Within a word document the variables are stored as a wideString. To get the handle of my app from within the DLL I call this function which queries the Add In's host word window: Result:=0; val := Doc.Variables.Item(i).Value; tryStrToInt(val, hdl); Result := Hdl; Result is a THandle. Debugging a 64 bit AddIn is a bit problematic. So I have not looked into it yet. However, I have written to a log file to output what is happening at the various stages. I know that the hdl being passed to SendMessage is the correct hdl of my app. Also GetLastError returns success after SendMessage (if that means anything!) On My app I show the value of its handle on a label when it is running. Let's say its 12345678. If I create another Delphi executable and call WinAPI.Windows.SendMessage(12345678, WM_COPYDATA, 0, Integer(@copyDataStruct)); That works as expected. If I do the same in my Add In DLL (ie substitute the hdl var with the Longint value of my app's handle) it doesn't work.
  15. Mark Williams

    FTPServer Beginner

    I am looking for some general guidance on how to go about setting up an FTP server for the first time. I have opted for TIDFTPServer for this purpose and have been through the help files and searched Google, but I have come up with very limited information. I don't want to launch into this in my usual bull in a china shop manner only to find later that I have gone about it in the least appropriate way. So apologies in advance for the broad nature of this topic. In essence my requirements are for a basic FTP Server. However, I want to try and strictly control what users can upload and, in particular, download. My fledgling thoughts: Uploads The user requests permission for upload via my webserver and if authenticated is issued with a unique token to be stored in the database along with an expiry time which the user will need to renew periodically via the webserver and an identifier to identify which folder(s) the user is allowed to upload to. The FTP client would submit the token to the FTP server which would retrieve the token, expiry time and folder identity prior to permitting any upload request. When the client has finished it will request the deletion of the token. There are likely often to be large numbers of files to be uploaded so preferably the FTP Server will be able to store the token, expiry time etc rather than querying the database for every upload. The FTP client would submit the token on every upload request. The FTP Server would check periodically whether the token has been removed. Downloads There may be a requirement for download of a large batch of files. So similar approach to the above. I already keep a record of every file in a database so each has a unique id and there is another table which records user rights to access a given file. Before submitting download request user applies for token via webserver and at the same time submits a list of ids of those file he intends to download. Webserver checks which ones user has access to and populates a table with the file ids ("permitted_files"). On receiving the retrieve request the FTP does the same as for upload, but additionally queries the "permitted_files" table to see which files the user is permitted to download. Questions Is this broadly a sensible approach? If not, how better to go about this? Assuming it is sensible, what do I need to implement this within the FTPServer component. My best guess at the moment is that it would be handled via CommandHandlers. No GUI interface is required and I don't really need a command line so how best to implement this on the Server: as a Windows service? As the FTP Server may be receiving numerous requests at the same time how best to manage the data relative to specific requests (ie tokens, permitted file ids etc).
  16. Mark Williams

    FTPServer Beginner

    Thanks to everyone for the detailed responses and suggestions. I think my fundamental error was my assumption (long-held and it seems with little basis) that FTP is faster than HTTP for multiple file transfers. I have already written an ISAPI dll using Delphi's TWebBroker which seems to be working well for my needs I just thought I could speed things up with FTP. From the above responses a better approach may be to more finely tune my ISAPI dll. The comments re Real Thin Client are noted and I will certainly look into this at a later point. In short, thanks for the feedback which it appears has saved me a potential mountain of unncessary work!
  17. Mark Williams

    Problem starting FTP Server

    I am trying to create a FTP server for the first time using TIDFTPServer. I have dropped a TFTPServer onto a form and changed properties only as follows: Active = True Bindings = < item IP = '**.**.***.***' Port = 21 end> ReuseSocket = rsTrue If I set the IP address as the external ip address for the server I get an EIDCouldNotBindSocket error and it advises that "Address and port are already in use" when I try to start it. I don't get this problem if I change the IP address to the server's local address (192.168.0.12). Should the IP address always be set to the local IP? I've noticed that IDFTP has an ExternalP property and also ServerHOST property. There is help on the ExternalIP property, but no on the ServerHOST property. Would I be right in assuming these properties are used for external connections to the FTP server rather than anything in the FTPServer's settings? With respect to the ExternalIP address this also seems to require setting of the DataPort. I have tried connecting setting ExternalIP to the relevant IP address and DataPort to 21. Host is blank. When I try to connect I get an error message telling me a Host is required. I've tried setting Host to the external IP and also ServerHost, but either I get Host required error or time out.
  18. Mark Williams

    TButtonedEdit Styles and transparency

    When using a dark theme with TButtonedEdit and an imagelist with DrawingStyle set to dsTransparent, the image always shows with a white background. That's obviously fine when the edit box is white, but not when it is dark. My images in the imagelist have a background colour of clFuschia. For some reason I can't change the transparent color in the imageList's editor. It is disabled and clDefault is selected. So I tried another approach, creating an imageList at runtime and adding masked images to it as follows: Function GetTransparentImageList(Owner:TComponent; SourceImages:TImageList; BMPIndex:Integer):TImageList; var bmp:TBitmap; begin bmp:=TBitmap.Create; try if SourceImages.GetBitmap(BMPIndex, bmp) then begin Result:=TImageList.Create(Owner); With Result do begin DrawingStyle:=dsTransparent; //tried with and without for all three color options below AddMasked(bmp, clNone); //tried with clFuchsia and clDefault end; end; finally bmp.Free; end; end; Still the TButtonedEdit stubbornly shows the button image with a white background. Am I missing something?
  19. Mark Williams

    TEncryptedZipFile

    @Uwe Raabe I have just had a look at this component on your blog. I could get it to write an encrypted zip file, which I can open manually no problem, but I cannot get it to decrypt using the component. I downloaded the amended unit from https://www.uweraabe.de/Blog/2017/05/07/tzipfile-with-password-encryption-part-3/, but this still didn't work for me. My code for unzipping is as follows: Zipper:=TEncryptedZipFile.Create('Mark'); Stream:=TMemoryStream.create; try DecompressionStream:=TStream.Create; Zipper.Open(OpenDialog1.filename, zmReadWrite); Zipper.Read('File', DecompressionStream, zh); Stream.CopyFrom(DecompressionStream, DecompressionStream.size); {Crashes here} DecompressionStream.Free; Stream.Position:=0; Stream.SaveToFile(ExtractFilePath(includeTrailingPathDelimiter(openDialog1.FileName))+'File.docx'); Zipper.Close; finally zipper.Free; stream.Free; end; I have used the same routine as I would for reading from the standard TZipFile ie using the DecompressionStream. Can't work out whether my approach is write or if there is a problem with the TEncryptedZipFile code. Anyways my debug output is: System.Classes TStream.ReadBuffer System.Classes 8340 +1 TStream.ReadBuffer uEncryptedZipFile 299 +9 TDecryptStream.Skip uEncryptedZipFile 277 +10 TDecryptStream.Seek System.Classes 7561 +1 TStream.SetPosition System.ZLib 2891 +32 TZDecompressionStream.Read System.ZLib 2939 +27 TZDecompressionStream.Seek System.Classes 7569 +2 TStream.GetSize
  20. Mark Williams

    FTP add virtual directory

    Using IIS. New to FTP. Can anyone please give me a steer as to how to programmatically add and configure virtual FTP directories in IIS via Delphi?
  21. Mark Williams

    FTP add virtual directory

    @Remy LebeauThanks for the detailed response. Are there any problems running an Indy FTP server alongside IIS? Also, do you know of any good sample FTP server projects anywhere?
  22. Mark Williams

    ShellExecute and passing of password

    I would like to shellexecute one app from another. Both apps require username and password. I would like to be able to pass the password securely from one app to the other. Obviously, command-line parameters are out and I would imaging a memory mapped file will also not be secure. Is there any relatively simple and secure way of achieving this.
  23. Mark Williams

    FTP add virtual directory

    Is it not possible to also password protect the folder? My intention is to maintain a record of the virtual folders in a database and require the user to signal continued use of the folder and as soon as there is a failure to do so the folder would be deleted. Is this the Overbyte stuff? I will have a look. So if I wanted to run IIS and ICS on the same server I would need a second static ip?
  24. Mark Williams

    FTP add virtual directory

    Thanks. I'll have a look at WMI. Which type library do you use? I've got a couple on my registered libraries.
  25. Mark Williams

    FTP add virtual directory

    Yes it's pretty easy to set up via IIS, but the security angle is precisely why I don't wish to do it this way. I want to check the user's credentials against database and then issue that user a one-off password for a single transaction and add a temporary ftp folder, which then gets removed as soon as the user has completed the transaction. There may be better ways of doing this. As I said I'm a FTP novice!
×