DWScript: TdwsGuardianThread.Finalize freeze when inside a DLL - dwscript

When dwsExprs is added to a DLL, his finalization section freeze. Actaully TdwsGuardianThread.Finalize is frozen on the line guardian.WaitFor.
To demonstrate the issue, I made a sample DLL, which is empty and only include dwsCript. I also made a test application loading the DLL and freeing it immediately. On exit the application freeze as I said above (Put a breakpoint on guardian.WaitFor to see that.
Sample DLL:
library DlltestDll;
uses
dwsExprs;
{$R *.res}
begin
end.
Sample application:
program DllTest;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows;
var
HDll : HMODULE;
begin
HDll := LoadLibrary('DllTestDll.dll');
FreeLibrary(HDll);
end.
I'm using XE4 and DWScript extracted from SVN repository may 26.
Any help appreciated.

The solution as DWScript is currently is the workaround I described in the comments above:
Add an exported function in the DLL which calls TdwsGuardianThread.Finalize and call that exported function from the main application before unloading the DLL. Later when dwsExprs finalization section is called, the guardian thread is already stopped and nothing freeze anymore
The sample DLL now looks like:
library DlltestDll;
uses
dwsExprs;
{$R *.res}
procedure Finalize; stdcall;
begin
TdwsGuardianThread.Finalize;
end;
exports
Finalize;
begin
end.
And the sample application is:
program DllTest;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows;
var
HDll : HMODULE;
Finalize : procedure; stdcall;
begin
HDll := LoadLibrary('DllTestDll.dll');
#Finalize := GetProcAddress(HDll, 'Finalize');
Finalize;
FreeLibrary(HDll);
end.

Related

go-redis does it have support for registering / executing lua functions

From its version 7.x onwards, Redis has introduced functions, as an alternative to script execution, as documented here.
I am looking for an example, or documentation on how to use redis functions using go-redis package. Not sure, if go-redis supports this feature yet.
Thanks for anyone letting me know about this.
I searched a bit more in the official documentation of go-redis, which has a way of executing unsupported commands using the Do, as mentioned here.
// Defind the function code..
fcode := `#!lua name=mylib
redis.register_function('myfunc',
function (keys, args)
return args[1]
end)`
// Load or replace the function
val, err := rdb.Do(ctx, "function", "load", "replace", "<function code text>").Result()
// later in the code... call the function
va, err := rdb.Do(ctx, "fcall", "myfunc", 0, "hello").Result()

DWScript Write/Read a simple text file

I would like to write/read a simple text file using dwscript.
My code is here below... but I am non able to get it run, please someone might help...:
(I am using the Simple.exe in the Demos folder of DWS installation)
// uses Classes;
{$INCLUDE_ONCE 'c:/.../System.Classes.pas'}
var
s: TFileStream;
o: string; // out
i: integer;
f: word; // flag
f := fmOpenReadWrite;
if not FileExists('C:\Temp\Junkfile.txt') then
f := f or fmCreate;
s := TFileStream.Create('C:\Temp\Junkfile.txt', f);
try
s.Position := s.Size; // will be 0 if file created, end of text if not
for i := 1 to 10 do begin
o := Format('This is test line %d'#13#10, [i]);
s.Write(o[1], Length(o) * SizeOf(Char));
end;
finally
s.Free;
end;
By default the script engine keeps everything sand-boxed and nothing that gives access outside the sandbox is exposed. So if you want to give access to arbitrary files to script you need to expose functions & classes to achieve it (through TdwsUnit f.i.).
Also it won't compile the Delphi classes unit, DWScript is not meant to be an alternative to the Delphi compiler, but to offer scripting support, ie. allow end users to run code in a way over which you have full control over what they can do, and that can't crash or corrupt the host application (that last point being the key differentiation with the other notable Pascal scripting engines).
You can use dwsFileFunctions to get basic file I/O support, in which case an equivalent to the file creation portion of your code would be something like
var f := FileCreate('C:\Temp\Junkfile.txt');
for var i := 1 to 10 do
FileWrite(f, Format('This is test line %d'#13#10, [i]));
FileClose(f);

Where the function ap_run_pre_connection in Apache httpd source code?

I'm reading the source code of the Apache2.2 and I found that when I use the prefork module,it call the ap_process_connection to deal with a connection and in this method it calls the ap_run_pre_connection.
When it comes to here,I can find neither ap_run_pre_connection nor pre_connection (I find a macro named AP_DECLARE_HOOK, it linked the ap and _hook_ before the name pre_connection).
Where can I find the next step?
You can find the modules that participate in this hook by looking for ap_hook_pre_connection.
AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c, void *csd),(c, csd),OK,DECLINED)
AP_IMPLEMENT_HOOK_RUN_ALL means multiple modules that called ap_hook_pre_connection() will be run until an error is returned
/**
* Implement an Apache core hook that runs until one of the functions
* returns something other than ok or decline. That return value is
* then returned from the hook runner. If the hooks run to completion,
* then ok is returned. Note that if no hook runs it would probably be
* more correct to return decline, but this currently does not do
* so. The implementation is called ap_run_<i>name</i>.
The actual impl of ap_run_pre_connection is just a macro that loops through a linked list of registered functions. See apr_hooks.h

How to bypass Internet Explorer Enhanced Security when using embedded WebBrowser control?

i have a native Windows application that embeds the WebBrowser, i.e.
CLSID_WebBrowser
8856F961-340A-11D0-A96B-00C04FD705A2
Shell.Explorer.2
Unfortunately, when running on Windows Servers, the Internet Explorer Enhanced Security mode interferes with the WebBrowser control, causing it to not render at all:
In this case, the UI of the software is driven as a WebBrowser control - making the software unusable.
i could disable Internet Explorer Enhanced Security mode, but that is not practical.
How can i instruct Internet Explorer browser to allow an embedded browser to render without the security dialog?
Note: i would have suggested adding about:security_Application.exe to the Trusted Zones list"
Sadly, that will require DRP/FRP validation, an ISO security assessment, and the security group will have to be called in to make the change. In addition, an RFC will need to be created so KPMG won't have hissy-fit next audit. i was hoping for the "good" solution.
See also
Customizing (disabling) security settings for IE control
Custom IInternetSecurityManager not being called with dialogs
You can specify a different URL. For example you can extract the content to a temp file and navigate to it. This will not put your content in the trusted zone, but it is better than the internet zone you get for the about protocol.
If you do not want to save the content, you can first navigate to about:blank, then in DocumentComplete, QI the document for IPersistMoniker, and call Load with a TInterfacedObject that basically simulates a url moniker.
The IMoniker.GetDisplayName implementation needs to return the URL. The url needs to be in a trusted zone.
IMoniker.BindToStorage implementation needs to send back a reference to a TMemoryStream when IStream is asked.
There's a third way, write a process-wide security manager that puts your url in a trusted zone.
The solution is to implement your own Internet Security Manager service creating an object that implements IInternetSecurityManager (see MSDN: Implementing a Custom Security Manager). There are five security zones:
Local: URLZONE_LOCAL_MACHINE (0)
Intranet: URLZONE_INTRANET (1)
Trusted: URLZONE_TRUSTED (2)
Internet: URLZONE_INTERNET (3)
Restricted: URLZONE_UNTRUSTED (4)
The only method you really need to worry about is MapUrlToZone:
TEmbeddedSecurityManager = class(TInterfacedObject, IInternetSecurityManager)
public
//...
function MapUrlToZone(pwszUrl: LPCWSTR; out dwZone: DWORD; dwFlags: DWORD): HResult; virtual; stdcall;
//...
end;
This method checks if the Url starts with about:security
about:security_Contoso.exe
and if so, returns that the zone should be Local:
function TEmbeddedSecurityManager.MapUrlToZone(pwszUrl: LPCWSTR; out dwZone: DWORD; dwFlags: DWORD): HResult;
var
url: UnicodeString;
begin
Result := INET_E_DEFAULT_ACTION;
{
https://msdn.microsoft.com/en-us/library/ms537133(v=vs.85).aspx
}
url := pwszUrl;
{
When IE Enchanced Security is enabled, the url goes from
about:blank_xxxx
to
about:security_xxxx
In that case we will put the page in the "Local" zone
}
if url.StartsWith('about:security') then
begin
dwZone := URLZONE_LOCAL_MACHINE; //Local
Result := S_OK;
end;
end;
Every other method must return INET_E_DEFAULT_ACTION (i.e. not S_OK nor E_NOTIMPL), e.g.:
function TEmbeddedSecurityManager.SetSecuritySite(Site: IInternetSecurityMgrSite): HResult;
begin
Result := INET_E_DEFAULT_ACTION;
end;
You give the embedded WebBrowser this service when it calls IServiceProvider.QueryService. In the case of Delphi's TEmbeddedWB control, it is exposed in the OnQueryService event:
function TForm1.EmbeddedWBQueryService(const rsid, iid: TGUID; out Obj: IInterface): HRESULT;
var
sam: IInternetSecurityManager;
begin
Result := E_NOINTERFACE;
//rsid ==> Service Identifier
//iid ==> Interface identifier
if IsEqualGUID(rsid, IInternetSecurityManager) and IsEqualGUID(iid, IInternetSecurityManager) then
begin
sam := TEmbeddedSecurityManager.Create;
Obj := sam;
Result := S_OK;
end;
end;
Maybe you could consider to load a different embedded browser. There is:
WebKit: http://www.webkit.org/
SWT (eclipse)

Running an application at the end of the uninstall in InnoSetup, handling the user cancelling

During un-installation, user will be asked "Are you sure to uninstall ...".
Then the user will click either "Yes" or "No".
Is it possible to catch this on the script?
Because I need to execute an application at the end of uninstallation process.
If I execute the application during "InitializeUninstall()", that is not correct because the user could cancel the uninstallation later (the above dialog is displayed AFTER this function).
Same with "DeInitializeUninstall()", this function is still executed even the user cancel the uninstallation.
Basically, I need to execute the application when the user is really un-installing (agreed to uninstall). Because I need to catch the ExitCode of this application to set the UninstallNeedRestart() function.
Thanks.
What you can do is add a global variable in your [Code] section
[Code]
var
ApplicationWasUninstalled: Boolean;
After that, in the InitializeUninstallProgressForm procedure you can set the global variable to 1 (Note: this function gets executed only if the user clicks Yes when they are prompted if they want to uninstall your application
procedure InitializeUninstallProgressForm();
begin
ApplicationWasUninstalled := true;
end;
Moving on, you will check the value of ApplicationWasUninstalled in DeinitializeUninstall function
procedure DeinitializeUninstall();
begin
if ApplicationWasUninstalled Then Begin
//your code here
end;
end;
Another way to achieve this is using the [Run] and / or [UninstallRun] sections to run an executable after install / before uninstall.
You can run a executable to do whatever clean up you need.
Compile a helper exe to do what you want, or add the function to your main executable when supplied a command line parameter.
[Run]
Filename: "{app}\CleanUp.exe"; WorkingDir: "{app}"
[UninstallRun]
Filename: "{app}\CleanUp.exe"; Parameters: "/uninstall"; WorkingDir: "{app}"; RunOnceId: "CleanUpApp"
More information in the inno setup documentation: http://www.jrsoftware.org/ishelp/index.php?topic=runsection
You need to add the helper exe to the installation too:
[Files]
...
Source: "C:\myprog\CleanUp.exe"; DestDir: "{app}"; Flags: ignoreversion
You can do this in the CurUninstallStepChanged() event function when it is called with the usPostUninstall parameter.
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usPostUninstall then
begin
// Do your uninstall time code here
Exec(ExpandConstant('{app}\CleanUp.exe'), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
end;
end;