Does LoadLibraryEx function use side-by-side manifests? I have bar.dll with embedded SxS manifest, and that manifest describes version of this bar.dll, other dll file foo.dll has manifest that lists bar.dll as dependency, with specified version. But when I try to load bar.dll from foo.dll with LoadLibraryEx("bar.dll", NULL, 0) I see (with enabled sls with gflags) that it ignores these manifests, and loads first version of bar.dll that it sees in searchpath, if I define ISOLATION_AWARE_ENABLED and use LoadLibrary it finds right version, but this ISOLATION_AWARE_ENABLED doesn't affect behaviour of LoadLibraryEx, I need to load right version with LoadLibraryEx because LoadLibraryEx is used implicitly for delayed loading of dll's. Is LoadLibraryEx supposed to work like this, or is it some problem in my project configuration?
foo dll
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="foo" version="0.1.2.3" type="win32"/>
<dependency>
<dependentAssembly>
<assemblyIdentity name="bar" version="0.1.2.3" type="win32" />
</dependentAssembly>
</dependency>
<file name="foo.dll">
</file>
</assembly>
bar.dll
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="bar" version="0.1.2.3" type="win32"/>
<file name="bar.dll">
</file>
</assembly>
LoadLibrary used active activation context of the calling thread. but which is this context ? why it must be from your foo.dll ? why not from xyz.dll or from exe ? really most time active activation context was exactly from exe.
if dll have own manifest - system create activation context for this dll and save it (until dll will be unloaded) but not make it active. and this is obviously - we have multiple dlls in process, but active context only one - from which dll select it ? from exe. however system activate (make it current active) dll activation context before call it entry point. and deactivate it after entry point return. but say inside another dll functions - (who called it ?) the context already not from your dll.
so solution must be next:
define 2 global variables in dll:
BOOL gActCtx;
HANDLE ghActCtx
on DLL_PROCESS_ATTACH save current activation context (it from your dll manifest)
gActCtx = GetCurrentActCtx(&ghActCtx);
free it on DLL_PROCESS_DETACH
if (gActCtx) ReleaseActCtx(ghActCtx);
and when you need load bar.dll do next:
if (gActCtx)
{
ULONG_PTR Cookie;
if (ActivateActCtx(ghActCtx, &Cookie))
{
LoadLibraryExW(L"bar.dll", NULL, 0);
DeactivateActCtx(0, Cookie);
}
}
Related
I have two questions regarding activation context API and SxS manifests. They look like very simple, but still I cannot find any good answer for them.
I have two dll libraries with filenames foo.dll and bar.dll, both with embedded manifests, foo depends on bar. Is there any way to assign these two with assemblyIdentity name other than their filename? For example if I want assembly identity of bar.dll to be CompanyName.Subsection.bar ? If I change it's identity like this - I get error while I try to load foo.dll "Dependent Assembly CompanyName.Subsection.bar,type="win32",version="0.1.2.3" could not be found". Of course if I specify name assembly identities as filenames (<assemblyIdentity name="bar") everything works, but is there a way to use these dotted names?
foo.dll
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="foo" version="0.1.2.3" type="win32"/>
<dependency>
<dependentAssembly>
<assemblyIdentity name="CompanyName.Subsection.bar" version="0.1.2.3" type="win32" />
</dependentAssembly>
</dependency>
<file name="foo.dll">
</file>
</assembly>
bar.dll
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="CompanyName.Subsection.bar" version="0.1.2.3" type="win32"/>
<file name="bar.dll">
</file>
</assembly>
It can be done if instead of embedding the manifest for bar.dll you place it in a separate folder together with the dll itself. I.e.:
foo.dll
CompanyName.Subsection.bar/
├── bar.dll
└── CompanyName.Subsection.bar.manifest
You still need to embed the first manifest into foo.dll. I'm confident that you can remove the following snippet from that manifest, because it's an embedded manifest and therefore needs not to specify what dlls belong to the assembly:
<file name="foo.dll">
</file>
The manifest for bar.dll is good, but be sure to name the folder and the manifest file exactly as specified in the assemblyIdentity element (see example folder structure above).
Also note, that you can diagnose problems related to loading SxS assemblies with the sxstrace command line tool. Step by step instructions:
Run sxstrace trace -logfile:mytrace.etl from a Visual Studio Command Line. The command will not return until you press ENTER. However, do not press ENTER yet.
Start the application that loads foo.dll to reproduce your issue
Then press ENTER in the Command Line window to stop sxstrace
You now have a file mytrace.etl, which is not human readable. Convert it to a readable format by running sxstrace parse -logfile:mytrace.etl -outfile:mytrace.txt. You get a file mytrace.txt which shows what happens, when you load foo.dll and where it fails to resolve some of its dependencies.
I am trying to get dropping a file into the application to work and so I compiled the example but every time I try to drop a file, I get the "not allowed to drop" symbol. I tried this also with my own example and in debug mode I find that none of the implemented functions (dragEnterEvent, dragMoveEvent, dropEvent) are even reached. What is the problem here / how do I fix this?
Also, running Qt 4.8 on Win7 x64
I found the issue: you cant drag and drop from a non escalated application (explorer.exe) to an escalated one.
Thanks to #HansPassant for the workaround: add a manifest file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="true"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
This manifest requires 'uiAccess' to be true and that requires the exe to be trusted and signed.
Note: the solution proposed in http://helgeklein.com/blog/2010/03/how-to-enable-drag-and-drop-for-an-elevated-mfc-application-on-vistawindows-7/ using ChangeWindowMessageFilter does NOT work.
I am creating a private side by side assembly and need to generate an Assembly manifest for that dll. The problem is that I don't know how I can specify a version to this manifest. (The version of dll/build is #defined in a header file)
I need to generate a manifest file like the one shown below. Present I uses a static manifest file with below content and specify it in project settings->Manifest Tool->Input and output->Additional Manifest Files. The only problem with this approach is that, I can't change the version.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="MyCompany.MyDll" version="1.0.0.0"
processorArchitecture="x86" ></assemblyIdentity>
</assembly>
Please advice, what is the correct procedure to create assembly file for private side by side dll.
I want to do exactly what it is described here, but the accepted solution does not work for me. I suppose the reason is explained here :
If a DLL with dependencies is loaded
by specifying a full path, the system
searches for the DLL's dependent DLLs
as if they were loaded with just their
module names.
If a DLL with the same module name is
already loaded in memory, the system
checks only for redirection and a
manifest before resolving to the
loaded DLL, no matter which directory
it is in. The system does not search
for the DLL.
I wish to have my application in the following structure.
c:\Exe
|
|----- c:\DLL\DLL.dll, c:\DLL\common.dll
|
|----- c:\DLL2\DLL2.dll, c:\DLL2\common.dll
My EXE will load the DLLs through
LoadLibrary("c:\\DLL\\DLL.dll");
LoadLibraryEx("c:\\DLL2\\DLL2.dll");
common is implicitly loaded in both cases.
I tried the SetDllDirectory option, but there is always only one common.dll loaded.
I added version information in common.dll. c:\DLL\common.dll has version 2.0.1.0 while c:\DLL2\DLL2.dll has version 4.0.1.0
I embedded the following manifest with the corresponding version info, but it did not help.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="common" version="4.0.1.0" processorArchitecture="x86"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>
Is there a solution to this problem ?
Where have you embedded the manifest? The EXE or the DLLs?
You have two basic ways of doing this, both involve turning "common" into a private SxS assembly by creating a manifest for it.
Then:
If DLL and DLL2 contain manifests listing dependent assemblies, then you need to add a dependentAssembly to their manifests specifying "acme.common" (for example) as a dependent assembly. As dependent assemblies are always searched for, by default, in the loading modules folder, each DLL will load its own local copy of common.
If you are just relying on the applications default activation context to do most of the heavy lifting, then you can try using the ActivationContext API.
Call CreateActCtx twice, specifying two the two different folders as the base folder for the resulting context.
In pseudo code:
HACTCTX h1 = CreateActCtx( ... for DLL ... );
HACTCTX h2 = CreateActCtx( ... for DLL2 ...);
ActivateActCtx(h1,...);
LoadLibrary("C:\\DLL\\DLL1.DLL");
DeactivateActCtx();
ActivateActCtx(h2,...);
LoadLibrary("C:\\DLL2\\DLL2.DLL");
DeactivateActCtx...
If the dlls already contain their own manifests the system will use those. If not, this will let you specify a search directory for private assemblies without modifying the dll's themselves.
To implement Option 1:
First, I don't recommend trying to use the dll name as the assembly name. So, create a manifest that looks like this in each folder:
<!-- acme.common.manifest -->
<assembly manifestVersion="1.0">
<assemblyIdentity type="Win32" name="acme.common" version="1.0.0.0" processorArchitecture="x86"/>
<file name="common.dll"/>
</assembly>
You can fix the version number to match common.dll's version in each folder, but thats not important.
Then, either the manifest you list, or a directive like this if you are using Visual Studio
#pragma comment(linker, "/manifestdependency:\"acme.common'"\
" processorArchitecture='*' version='1.0.0.0' type='win32'\"")
Just make sure the dependent assembly versions match the versions of the corresponding 'acme.common' assembly.
Some of the controls I've created seem to default to the old Windows 95 theme, how do I prevent this? Here's an example of a button that does not retain the Operating System's native appearance (I'm using Vista as my development environment):
HWND button = CreateWindowEx(NULL, L"BUTTON", L"OK", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
170, 340, 80, 25, hwnd, NULL, GetModuleHandle(NULL), NULL);
I'm using native C++ with the Windows API, no managed code.
To add a manifest to the application you need create a MyApp.manifest file and add it to the application resource file:
//-- This define is normally part of the SDK but define it if this
//-- is an older version of the SDK.
#ifndef RT_MANIFEST
#define RT_MANIFEST 24
#endif
//-- Add the MyApp XP Manifest file
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "MyApp.manifest"
With newer versions of Visual Studio there is a Manifest Tool tab found in the project settings and the Additional Manifest Files field found on this tab can also be used to define the manifest file.
Here is a simple MyApp.manifest file for a Win32 application:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.1"
processorArchitecture="X86"
name="Microsoft.Windows.MyApp"
type="win32"
/>
<description>MyApp</description>
</assembly>
If you application depends on the other dlls these details can also be added to the manifest and Windows will use this information to make sure your application always uses the correct versions of these dependent dlls.
For example here are the manifest dependency details for the common control and version 8.0 C runtime libraries:
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.VC80.CRT"
version="8.0.50608.0"
processorArchitecture="x86"
publicKeyToken="1fc8b3b9a1e18e3b" />
</dependentAssembly>
I believe it has got nothing to do with your code, but you need to set up a proper manifest file to get the themed controls.
Some info here: #msdn.com and here: #blogs.msdn.com
You can see a difference between application with and without manifest here: heaventools.com