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
#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;
}
#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
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)

Attachment: pgp31GQPU8edP.pgp
Description: PGP signature

Reply via email to