WinInet, Proxies and NTLM

For quite some time now I heard about customers telling me that PopScan seems to be having problems with proxy servers using NTLM authentication. I knew that and I told everyone that this is not supported.

But I could not understand it: Why did it not work. I mean, I went from my own HTTP-Routines to WinInet just to be able to use the system-wide proxy server settings and connections

When using WinInet and INTERNET_OPEN_TYPE_PRECONFIG with InternetOpen, the whole thing is supposed to just work – as long as IE itself does work. But in my application this wasn’t the case and I had no idea why. As soon as NTLM was enabled at the proxy, I was just getting a 407 HTTP_PROXY_AUTHENTICATION_REQUIRED status from the proxy, despite the correct password being used

MSDN was of help (taken from the documentation of InternetOpenRequest):

If authentication is required, the INTERNET_FLAG_KEEP_CONNECTION flag should be used in the call to HttpOpenRequest. The INTERNET_FLAG_KEEP_CONNECTION flag is required for NTLM and other types of authentication in order to maintain the connection while completing the authentication process

I’ve added this flag (and some more – now that I already was at it), recompiled, tested and -yes- finally it does what it should: It works just out of the box. No more 407, no more entering password for the users. One more thing that switched its state from “not supported” to “supported and working splendidly”.

This is with a NTLM-enabled Squid Proxy, but it should work with Microsoft ISA too.

Debugging

Debugging can be so much fun if you just know how to entertain yourself while doing it. I’ve taken the screenshot below when I did some debugging on a stupid AV and finally found why it happens. Then I’ve added a Gexperts Debug-Statement to visualize whether I was right.

debug_fun.png

It seems, I was…. Talk about programs not knowing when it’s time to die. If only Delphi itself could tell me before it’s crashing…

(read the thing from bottom to top: 19:00 ’till 19:02 I was debugging and the app was crashing. Then I found the problem, added the debug-statement which checks for a NULL-Pointer and outputs the message if there’s indeed one of them and at 19:02:42 I ran the thing again and it warned me that it’s going to crash. At 19:05:46 it was fixed)

Responding to search-strings

I’ve just looked at the logs of this webserver and – under the search strings used to find this page, found this: <blockquote>delphi cannot debug anymore</blockquote>It happens that tough I have not written about this particular topic, I certainly have some hints to this fellow searcher (although, they possibly come to late now):

  • Have you compiled your project with debug information? (Project/Options/Compiler).
  • Have you rebuilt your project after changing above settings?
  • Do your files by any chance have Unix-Lineendings? If so, the debugger won’t work
  • Have you restarted your PC? Sometimes this works too.

I’m quite sure there are more things that could make the debugger unusable, but unfortunatly I can’t currently think of any more of them. Maybe becuase just the ones listed above are common enough that I remeber them? Delphi is very nice, but sometimes it can be so unstable

Delphi, WinXP and Password Edits

I’m still into making Delphi apps look more “native” when run under Windows XP. Now that I got the IE-Control working, I was looking into the password-edit case.

The Problem: When using the standard way for creating password edits (Drop a TEdit on the Form and set the PasswordChar property to ° ), this may look and work on in Win 9x, NT and 2000, but under XP, some features are missing:

  • In XP, password-edits cannot be read from other applications by sending the WM_GETTEXT message. Delphi’s TEdit can.
  • In XP, the edits have a nice bullet instead of a * to mark the entered characters
  • When CapsLock is active, a balloon-hint appears warning the user that maybe she is not doing what she expects

    How to fix this?

    Simple: Create a descendant of TEdit, override CreateParams and set the controls style to ES_PASSWORD. Provided you are supplying a valid Manifest for XP, you now have a fully fledged and nice working password-edit:

    procedure TPasswordEdit.CreateParams(var Params: TCreateParams);
    begin
      inherited;
      Params.Style := Params.Style or ES_PASSWORD;
    end;
    

    Oh. One thing is still missing: The dots look wrong. This is because Delphi does not use Windows’ standart font per default but overrides this with “MS Sans Serif” where “Tahoma” is the standard under XP. So Delphi-Apps generally look kind of foreign – even more so, when ClearType is enabled (MS Sans Serif is a bitmap font and cannot be antialiased).

    This can be fixed by setting each forms DesktopFont property to true. Note that it’s a protected property, so it must me called from withing the form.

    Now the bullets look right and the font’s in your application are proper anti-aliased (provided ParentFont is set to true in every component on the form).

    delphi_pwchar.png

Delphi, Windows XP, Styles and embedded IE

Let’s say you have a delphi (delphi 7 – altough prior versions can use Mike Lischkes Theme Manager application which embedds the Microsoft Internet Explorer ActiveX Control. Let’s assume furhter that you have created your Manifest so the application appears in the themed style under Windows XP.

Unfortunatly, the embedded IE does not do that: Controls are still drawn in the old theme-less style. Why? How to tell the Control to use the themed style (which it certainly supports – just look at IE itself)?

For long I was looking for a solution which I’ve just found.

First, call SetThemeAppProperties (defined in UxTheme.pas), then send WM_THEMECANGED to your forms – at least to the one that uses the IE-Control. Example:

  SetThemeAppProperties( STAP_ALLOW_NONCLIENT OR
       STAP_ALLOW_CONTROLS OR
       STAP_ALLOW_WEBCONTENT );
  PostMessage(frmBrowser.Handle, WM_THEMECHANGED, 0, 0);

Especially important is the flag STAP_ALLOW_WEBCONTENT

Then, in the form containing the browser, just add a message-procedure:

Form-declaration:

  private
    procedure wmthemechanged (var msg: TMessage); message wm_themechanged;

Update: I’ve turned off the comment-feature as this entry somehow got listed in some spammers database. I’m currently deleting about 10 entries per day that are just there to provide links to some stange sites. I’ll post about this later.

JclDebug

If you are a Delphi Programmer like me, you surely know the problem with users reporting an exception here and there but you cannot reproduce it at your place. This can get even more dramatical if such exceptions are thrown within threads as this will lead to an immediate bluescreen in Windows 9x/ME and to a “visit” by Dr. Watson in the NT-based versions of windows.

Imagine you could get a detailed error-report containing a full callstack of where the error occured combined with information about file and line-number. This report could be generated directly on the users computer and be sent to you via email or directly via the internet, using a custom procedure – even directly creating entries in the bugtracking-tool you are using.

This and more is made possible by the Project JEDI – more accuratly, the JCL-Subproject with its JclDebug-Framework. When you have completed the installation of the package, a new Menu Option called “Inser JCL Debug Data” will be added to the Project-Menu of your Delphi-IDE.

Now you add an Exception-Dialog to the Application using “File, New, Other…” followed by “Dialog, Exception Dialog”.

The newly added Form can easily be customized to your likings.

Now make a complete build. The IDE-Plugins will create a MAP-File, compress it and add it to the .EXE-File of your Project. When an Exception is thrown, the new error-dialog will be used, displaying a complete callstack with filenames and linenumbers.

I’ve created a small CGI-Script for receiving such reports and automatically filing it into my phpBugTracker (a very nice “Bugzilla-Light” written in PHP). This has already helped me to track two stupid bugs down which I was never able to reproduce on my development system.

Oh and before I forget: The whole thing can be downloaded on it’s Webpage at Sourceforge.