Hi all,
I just though I would follow up with a work around for this problem in case anybody searching the support forum has the same issue.
Just to re-cap:
- The production system is a Windows 2008 R2 Remote Desktop Host Server.
- My program only fails on this server with no predictable pattern
- The program works on the test environment without issue
- The program works on other remote desktop host servers that this customer has serving other sites without issue
- No other user / customer is reporting a similar problems. (About 1000 users spread over 60 customers)
After taking Danijel suggestion I moved the data module creation to the OnFormCreate event of the main form and comment out everything else. Unfortunately I still got the hit a miss exception in rtutils.dll. So I modified a copy of TRtcWInetHttpClientProvider to dump convert all of the parameters used for the WinInet calles to HEX strings and sent them to the debugger for display. This revealed that the data lengths and HEX strings were identical when comparing a successful run to a failed run.
I then on further to investigate potential memory errors using FastMM. This revealed nothing. Dumping the call stacks before calling HttpSendRequest revealed they were identical. Using madExcept (
http://madshi.net/) I was able to get a call stack listing when rtutills.dll produced the access violation. It showed the following stack:
00000008 0.08527645 [13320] Prime 4 - Access violation at address 70D31ED6 in module 'rtutils.dll'. Write of address 70D31ED6
00000009 0.62387568 [13320] Prime 4 - 70d31ed6 rtutils.dll
00000010 0.62402391 [13320] Prime 4 - 70d323f1 rtutils.dll TraceRegisterExA
00000011 0.62416679 [13320] Prime 4 - 6fb55d8c RASAPI32.dll RasEnumEntriesW
00000012 0.62430614 [13320] Prime 4 - 75946ce4 wininet.dll #101
00000013 0.62445301 [13320] Prime 4 - 75995891 wininet.dll HttpSendRequestA
00000014 0.62462616 [13320] Prime 4 - 009a20fe Prime4current.exe rtcWInetHttpCliProv 951 TRtcWInetHttpClientProvider.SendHeaderOutEx
Having had some help from Madshi it turns out that stack tracing into system DLLs can be a bit hit and miss, especially when matching up function names.
In the end I managed to persuade the user to add my EXE file to the data execution prevention (DEP) exception list for the server. As soon as he did this the program worked without any issues. The moment the program was removed from the exception list it failed again. Having set my Windows 7 development machine to use the same DEP setting the fault doesn't occur. The program also works correctly on all our Windows 2008 R2 servers and the test remote desktop host I set-up at the start of this problem. All of which have the same settings for DEP as the customers remote desktop server does.
Given this information I found a Windows API function called SetProcessDEPPolicy
http://msdn.microsoft.com/en-us/library/bb736299%28v=vs.85%29.aspx. Depending on the parameter passed into this function it will ask for the process to be included or excluded from the DEP monitoring. The Windows OS needs to have DEP configured to either use "Opt In" or "Opt Out" for the function call to work. The "Opt In" setting is the default setting for desktop systems and the "Opt Out" setting is the default setting for server systems. If the user has changed the configuration to be "Always Off" or "Always On" then this function call will not work.
Here is the function I have created to toggle the DEP protection for my program. It is a modified version of the code show in post 2 of this thread
http://stackoverflow.com/questions/8066266/how-can-i-enable-dep-nx-and-aslr-on-a-delphi-2006-or-earlier-executable
procedure ChangeDEPPolicy(Enabled: Boolean);
const
PROCESS_DEP_DISABLE : DWORD=$00000000;
PROCESS_DEP_ENABLE : DWORD=$00000001;
PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION : DWORD=$00000002;
var
SetProcessDEPPolicy: function(dwFlags: DWORD): BOOL; stdcall;
begin
SetProcessDEPPolicy := GetProcAddress(GetModuleHandle(kernel32), 'SetProcessDEPPolicy');
if Assigned(SetProcessDEPPolicy) then begin
if Enabled then begin
if not SetProcessDEPPolicy(PROCESS_DEP_ENABLE) then begin
OutputDebugString('Unable to opt in to the DEP protection.');
end;
end
else begin
if not SetProcessDEPPolicy(PROCESS_DEP_DISABLE) then begin
OutputDebugString('Unable to opt out of the DEP protection.');
end;
end;
end;
end;
Making this the first function call in my program has switched off the DEP checking for my program and it operates on the customers server without any further problems. I know this hasn't got to the real cause of the problem. If anybody has any tips for getting to the cause of problems caused by DEP protection in Windows please let me know.
I hope this information might be of help to somebody if they have a similar problem.
Take care,
Ryan