Cygport and auto-manifestize compatibility manifest
Corinna Vinschen
corinna-cygwin@cygwin.com
Wed Nov 20 16:02:00 GMT 2013
On Nov 20 16:01, Corinna Vinschen wrote:
> On Nov 20 09:47, Charles Wilson wrote:
> > On 11/20/2013 8:28 AM, Corinna Vinschen wrote:
> > >Apart from the fact that it would be nice if our linker would do this
> > >automatically and transparently,
> >
> > Or libtool, if you use it to link your exe? PTC...since
> > $new-libtool is pretty high on my to-do list.
> >
> > It'd be better if there was an option to ld/gcc, of course -- but
> > the details would be rather complicated. You wouldn't want to
> > invoke a separate executable like windres b/c then your build
> > recipe/makefile would have to change. Best if $LD_FLAGS could be
> > used... maybe something hideously ugly like -w32-manifest-compat
> > <file> [1] where <file> is not a full XML manifest, but rather
> > contains a list of GUIDs [2], and ld/gcc autogenerates the manifest
> > with just that stuff.
> >
> > That way, if you manually create a manifest (for other purposes),
> > you could just /not/ use the new flag.
>
> The other way around. If your project does not link in a resource
> anyway, which means that your project is WIn32 aware, then ld should
> add the manifest resource by default. Everything else means that
> you have to tweak all project configury, which is only barely descibed
> by a can of worms...
>
> A simple windres call in cygport would be nice, but unfortunately windres
> does not yet have this capability to add a resource to an existing exe.
>
> > I know, SHTDI...
>
> Yes, that's pretty much the problem. Even my ugly workaround is bad,
> because it only works on Windows. No more cross-building on Linux :-P
I added the sources for my now radically simplified test to this mail.
It consists of three files:
add-cygwin-default-manifest.c: The source code adding the manifest.
cygwin-default-mainfest.rc: The default resource containing the
manifest. It's target-agnostic.
Makefile: The Makefile.
To build the executable, just run `make'. This creates the
add-cygwin-default-manifest executable with the embedded manifest.
To add a manifest to binary "foo.exe", run `make doit EXE=foo.exe'
add-cygwin-default-manifest.exe pulls its own manifest and copies it
over to foo.exe. This is the step which I didn't manage to reproduce
via objcopy.
Note the crude way how `make doit' works. The UpdateResource
functionality is *extremly* sensitive against having an open handle to
the file still open in the same binary somewhere. If you try something
like this:
doit:
strip $(EXE)
objcopy --remove-section=.gnu_debuglink $(EXE)
./add-cygwin-default-manifest $(EXE)
then you'll get an error message "EndUpdateResource: Win32 error 5".
Apparently, `make' has an open handle to $(EXE) and this is propagated
somehow to the child processes. As a side note, trying to call, say,
GetBinaryType before calling BeginUpdateResource, or even stuff like
CreateFile/CloseHandle(!!!) will end up with "EndUpdateResource: Win32
error 5". As I wrote, *extremly* sensitive. That sounds much better
than "badly written"...
Corinna
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat
-------------- next part --------------
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <locale.h>
#include <sys/cygwin.h>
int
main (int argc, char **argv)
{
PWCHAR wpath;
HGLOBAL hResLoad; // handle to loaded resource
HMODULE hExe; // handle to existing .EXE file
HRSRC hRes; // handle/ptr. to res. info. in hExe
LPVOID lpResLock; // pointer to resource data
HANDLE h;
setlocale (LC_ALL, "");
if (argc != 2)
{
fprintf (stderr, "Usage: %s file\n", argv[0]);
return 1;
}
wpath = cygwin_create_path (CCP_POSIX_TO_WIN_W, argv[1]);
if (!wpath)
{
fprintf (stderr, "cygwin_create_path: %s\n", strerror (errno));
return 1;
}
hExe = GetModuleHandle (NULL);
hRes = FindResourceW(hExe,
MAKEINTRESOURCEW (CREATEPROCESS_MANIFEST_RESOURCE_ID),
MAKEINTRESOURCEW (RT_MANIFEST));
if (!hRes)
{
fprintf (stderr, "FindResourceW: Win32 error %d\n", GetLastError ());
return 1;
}
hResLoad = LoadResource(hExe, hRes);
if (!hResLoad)
{
fprintf (stderr, "LoadResource: Win32 error %d\n", GetLastError ());
return 1;
}
lpResLock = LockResource(hResLoad);
if (!lpResLock)
{
fprintf (stderr, "LockResource: Win32 error %d\n", GetLastError ());
return 1;
}
h = BeginUpdateResourceW (wpath, FALSE);
if (!h)
{
fprintf (stderr, "BeginUpdateResourceW: Win32 error %d\n",
GetLastError ());
return 1;
}
if (!UpdateResourceW (h, MAKEINTRESOURCEW (RT_MANIFEST),
MAKEINTRESOURCEW (CREATEPROCESS_MANIFEST_RESOURCE_ID),
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
lpResLock, SizeofResource(hExe, hRes)))
{
fprintf (stderr, "UpdateResourceW: Win32 error %d\n", GetLastError ());
return 1;
}
if (!EndUpdateResource (h, FALSE))
{
fprintf (stderr, "EndUpdateResource: Win32 error %d\n", GetLastError ());
return 1;
}
return 0;
}
-------------- next part --------------
#include <windows.h>
LANGUAGE 0, 0
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST MOVEABLE PURE DISCARDABLE
BEGIN
"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>\n"
"<assembly xmlns=""urn:schemas-microsoft-com:asm.v1"" manifestVersion=""1.0"">\n"
" <trustInfo xmlns=""urn:schemas-microsoft-com:asm.v3"">\n"
" <security>\n"
" <requestedPrivileges>\n"
" <requestedExecutionLevel level=""asInvoker"" uiAccess=""false""/>\n"
" </requestedPrivileges>\n"
" </security>\n"
" </trustInfo>\n"
" <compatibility xmlns=""urn:schemas-microsoft-com:compatibility.v1"">\n"
" <application>\n"
" <!--The ID below indicates application support for Windows Vista -->\n"
" <supportedOS Id=""{e2011457-1546-43c5-a5fe-008deee3d3f0}""/>\n"
" <!--The ID below indicates application support for Windows 7 -->\n"
" <supportedOS Id=""{35138b9a-5d96-4fbd-8e2d-a2440225f93a}""/>\n"
" <!--The ID below indicates application support for Windows 8 -->\n"
" <supportedOS Id=""{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}""/>\n"
" <!--The ID below indicates application support for Windows 8.1 -->\n"
" <supportedOS Id=""{1f676c76-80e1-4239-95bb-83d0f6d0da78}""/> \n"
" </application>\n"
" </compatibility>\n"
"</assembly>\n"
END
-------------- next part --------------
OBJS=add-cygwin-default-manifest.o cygwin-default-manifest.o
all: add-cygwin-default-manifest.exe
cygwin-default-manifest.o: cygwin-default-manifest.rc
windres -o $@ $<
add-cygwin-default-manifest.exe: $(OBJS)
gcc $(CFLAGS) -o $@ $(OBJS)
doit:
objcopy --remove-section=.gnu_debuglink $(EXE) $(EXE).out \
&& ./add-cygwin-default-manifest $(EXE).out \
&& strip $(EXE).out \
&& mv $(EXE).out $(EXE)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin-apps/attachments/20131120/a35941a7/attachment.sig>
More information about the Cygwin-apps
mailing list