git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Embed an application manifest on MinGW
@ 2011-05-28 19:58 Cesar Eduardo Barros
  2011-05-28 20:44 ` [msysGit] " Johannes Schindelin
  0 siblings, 1 reply; 5+ messages in thread
From: Cesar Eduardo Barros @ 2011-05-28 19:58 UTC (permalink / raw)
  To: msysgit; +Cc: git, Cesar Eduardo Barros

On Windows Vista, not having an application manifest with a
requestedExecutionLevel can cause several kinds of confusing behavior.

The first and more obvious is Installer Detection, where sometimes
Windows decides (by looking at things like the file name and even
sequences of bytes within the executable) that an executable is an
installer and should run elevated (causing the well-known popup dialog
to appear). On git, this happens for executables with names containing
"patch" or "update".

The second and more confusing is File Virtualization. With it, writes to
some files which should fail are instead redirected to somewhere else,
and reads to files might return different contents if a previous write
was redirected. Even more confusing, not all writes are redirected; I
recall reading somewhere that for instance writes to .exe files will
fail instead of redirecting.

Needless to say, git wants none of that. Not only that, but File
Virtualization has been blamed for dramatic slowdowns in git (see for
instance http://code.google.com/p/msysgit/issues/detail?id=320).

There are two ways to turn off these annoyances. Either you embed an
application manifest within all your executables, or you add an external
manifest (a file with the same name followed by .manifest) to all your
executables. Since for git some executables are copied (or hardlinked)
with several names, it is simpler and more robust to embed an internal
manifest.

A recent enough MSVC compiler should already embed a working internal
manifest, but for mingw you have to do so by hand.

Very lightly tested on Wine, where like on Windows XP it should not make
any difference.

References:
  - New UAC Technologies for Windows Vista
    http://msdn.microsoft.com/en-us/library/bb756960.aspx
  - Create and Embed an Application Manifest (UAC)
    http://msdn.microsoft.com/en-us/library/bb756929.aspx

Signed-off-by: Cesar Eduardo Barros <cesarb@cesarb.net>
---
 Makefile                  |   29 +++++++++++++++++++++--------
 compat/win32/git.manifest |   11 +++++++++++
 compat/win32/resource.rc  |    1 +
 3 files changed, 33 insertions(+), 8 deletions(-)
 create mode 100644 compat/win32/git.manifest
 create mode 100644 compat/win32/resource.rc

diff --git a/Makefile b/Makefile
index dec4a7f..3dbcdfb 100644
--- a/Makefile
+++ b/Makefile
@@ -323,6 +323,7 @@ XGETTEXT = xgettext
 PTHREAD_LIBS = -lpthread
 PTHREAD_CFLAGS =
 GCOV = gcov
+WINDRES = windres
 
 export TCL_PATH TCLTK_PATH
 
@@ -343,6 +344,7 @@ BUILTIN_OBJS =
 BUILT_INS =
 COMPAT_CFLAGS =
 COMPAT_OBJS =
+RESOURCE_OBJS =
 EXTRA_CPPFLAGS =
 LIB_H =
 LIB_OBJS =
@@ -1174,6 +1176,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	NO_INET_PTON = YesPlease
 	NO_INET_NTOP = YesPlease
 	NO_POSIX_GOODIES = UnfortunatelyYes
+	APPLICATION_MANIFEST = YesPlease
 	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/win32
 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
 	COMPAT_OBJS += compat/mingw.o compat/winansi.o \
@@ -1551,6 +1554,11 @@ ifdef USE_NED_ALLOCATOR
        COMPAT_OBJS += compat/nedmalloc/nedmalloc.o
 endif
 
+ifdef APPLICATION_MANIFEST
+	# Cannot be in LIB_OBJS because it must always be linked in
+	RESOURCE_OBJS += compat/win32/resource.o
+endif
+
 ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
 	export GIT_TEST_CMP_USE_COPIED_CONTEXT
 endif
@@ -1586,6 +1594,7 @@ ifndef V
 	QUIET_LNCP     = @echo '   ' LN/CP $@;
 	QUIET_XGETTEXT = @echo '   ' XGETTEXT $@;
 	QUIET_GCOV     = @echo '   ' GCOV $@;
+	QUIET_WINDRES  = @echo '   ' RC $@;
 	QUIET_SP       = @echo '   ' SP $<;
 	QUIET_SUBDIR0  = +@subdir=
 	QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
@@ -1685,9 +1694,9 @@ git.o: common-cmds.h
 git.sp git.s git.o: EXTRA_CPPFLAGS = -DGIT_VERSION='"$(GIT_VERSION)"' \
 	'-DGIT_HTML_PATH="$(htmldir_SQ)"'
 
-git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)
+git$X: git.o $(BUILTIN_OBJS) $(RESOURCE_OBJS) $(GITLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \
-		$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
+		$(BUILTIN_OBJS) $(RESOURCE_OBJS) $(ALL_LDFLAGS) $(LIBS)
 
 help.sp help.o: common-cmds.h
 
@@ -2011,17 +2020,17 @@ compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \
 	-DNDEBUG -DOVERRIDE_STRDUP -DREPLACE_SYSTEM_ALLOCATOR
 endif
 
-git-%$X: %.o $(GITLIBS)
+git-%$X: %.o $(RESOURCE_OBJS) $(GITLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
 
-git-imap-send$X: imap-send.o $(GITLIBS)
+git-imap-send$X: imap-send.o $(RESOURCE_OBJS) $(GITLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 		$(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)
 
-git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)
+git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(RESOURCE_OBJS) $(GITLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 		$(LIBS) $(CURL_LIBCURL)
-git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
+git-http-push$X: revision.o http.o http-push.o $(RESOURCE_OBJS) $(GITLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 		$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
 
@@ -2031,10 +2040,14 @@ $(REMOTE_CURL_ALIASES): $(REMOTE_CURL_PRIMARY)
 	ln -s $< $@ 2>/dev/null || \
 	cp $< $@
 
-$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(GITLIBS)
+$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(RESOURCE_OBJS) $(GITLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 		$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
 
+%.o: %.rc
+	$(QUIET_WINDRES)$(WINDRES) $< $@
+compat/win32/resource.o: compat/win32/git.manifest
+
 $(LIB_FILE): $(LIB_OBJS)
 	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
 
@@ -2167,7 +2180,7 @@ test-svn-fe$X: vcs-svn/lib.a
 
 .PRECIOUS: $(TEST_OBJS)
 
-test-%$X: test-%.o $(GITLIBS)
+test-%$X: test-%.o $(RESOURCE_OBJS) $(GITLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS)
 
 check-sha1:: test-sha1$X
diff --git a/compat/win32/git.manifest b/compat/win32/git.manifest
new file mode 100644
index 0000000..a82605c
--- /dev/null
+++ b/compat/win32/git.manifest
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+	<assemblyIdentity type="win32" name="Git" processorArchitecture="x86" version="0.0.0.0" />
+	<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+		<security>
+			<requestedPrivileges>
+				<requestedExecutionLevel level="asInvoker" uiAccess="false" />
+			</requestedPrivileges>
+		</security>
+	</trustInfo>
+</assembly>
diff --git a/compat/win32/resource.rc b/compat/win32/resource.rc
new file mode 100644
index 0000000..c2bf4a6
--- /dev/null
+++ b/compat/win32/resource.rc
@@ -0,0 +1 @@
+1 24 "git.manifest"
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [msysGit] [PATCH] Embed an application manifest on MinGW
  2011-05-28 19:58 [PATCH] Embed an application manifest on MinGW Cesar Eduardo Barros
@ 2011-05-28 20:44 ` Johannes Schindelin
  2011-05-28 21:07   ` Cesar Eduardo Barros
  0 siblings, 1 reply; 5+ messages in thread
From: Johannes Schindelin @ 2011-05-28 20:44 UTC (permalink / raw)
  To: Cesar Eduardo Barros; +Cc: msysgit, git

Hi,

On Sat, 28 May 2011, Cesar Eduardo Barros wrote:

> [...]
> @@ -1551,6 +1554,11 @@ ifdef USE_NED_ALLOCATOR
>         COMPAT_OBJS += compat/nedmalloc/nedmalloc.o
>  endif
>  
> +ifdef APPLICATION_MANIFEST
> +	# Cannot be in LIB_OBJS because it must always be linked in
> +	RESOURCE_OBJS += compat/win32/resource.o
> +endif
> +
>  ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
>  	export GIT_TEST_CMP_USE_COPIED_CONTEXT
>  endif
> [...]
>  
> -git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)
> +git$X: git.o $(BUILTIN_OBJS) $(RESOURCE_OBJS) $(GITLIBS)
> [...]
>  
> -git-%$X: %.o $(GITLIBS)
> +git-%$X: %.o $(RESOURCE_OBJS) $(GITLIBS)
> [...]
>  
> -git-imap-send$X: imap-send.o $(GITLIBS)
> +git-imap-send$X: imap-send.o $(RESOURCE_OBJS) $(GITLIBS)
> [...]
>  
> -git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)
> +git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(RESOURCE_OBJS) $(GITLIBS)
> [...]
> -git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
> +git-http-push$X: revision.o http.o http-push.o $(RESOURCE_OBJS) $(GITLIBS)
> [...]
>  
> -$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(GITLIBS)
> +$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(RESOURCE_OBJS) $(GITLIBS)
> [...]
>  
> -test-%$X: test-%.o $(GITLIBS)
> +test-%$X: test-%.o $(RESOURCE_OBJS) $(GITLIBS)
> [...]

Is it possible that adding the resource object to GITLIBS would reduce the 
patch and be "more correct", too?

Thanks,
Johannes

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [msysGit] [PATCH] Embed an application manifest on MinGW
  2011-05-28 20:44 ` [msysGit] " Johannes Schindelin
@ 2011-05-28 21:07   ` Cesar Eduardo Barros
  2011-05-28 21:19     ` Johannes Schindelin
  0 siblings, 1 reply; 5+ messages in thread
From: Cesar Eduardo Barros @ 2011-05-28 21:07 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: msysgit, git

Em 28-05-2011 17:44, Johannes Schindelin escreveu:
> On Sat, 28 May 2011, Cesar Eduardo Barros wrote:
>> [...]
>> @@ -1551,6 +1554,11 @@ ifdef USE_NED_ALLOCATOR
>>          COMPAT_OBJS += compat/nedmalloc/nedmalloc.o
>>   endif
>>
>> +ifdef APPLICATION_MANIFEST
>> +	# Cannot be in LIB_OBJS because it must always be linked in
>> +	RESOURCE_OBJS += compat/win32/resource.o
>> +endif
>> +
>>   ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
>>   	export GIT_TEST_CMP_USE_COPIED_CONTEXT
>>   endif
>> [...]
>>
>> -git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)
>> +git$X: git.o $(BUILTIN_OBJS) $(RESOURCE_OBJS) $(GITLIBS)
>> [...]
>>
>> -git-%$X: %.o $(GITLIBS)
>> +git-%$X: %.o $(RESOURCE_OBJS) $(GITLIBS)
>> [...]
>
> Is it possible that adding the resource object to GITLIBS would reduce the
> patch and be "more correct", too?

I thought about it, but it felt wrong. It is not a library, it is an object.

Also, while adding it to GITLIBS would add the object to all the right 
rules (in fact, I did a search for GITLIBS to find all the places to add 
the new object to), I believe it would get the object linked twice in 
some of the rules (the ones which do a $(filter %.o,$^) would get it 
both from GITLIBS via the filter and from GITLIBS via $(LIBS) on the 
command line).

-- 
Cesar Eduardo Barros
cesarb@cesarb.net
cesar.barros@gmail.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [msysGit] [PATCH] Embed an application manifest on MinGW
  2011-05-28 21:07   ` Cesar Eduardo Barros
@ 2011-05-28 21:19     ` Johannes Schindelin
  2011-05-28 21:50       ` Cesar Eduardo Barros
  0 siblings, 1 reply; 5+ messages in thread
From: Johannes Schindelin @ 2011-05-28 21:19 UTC (permalink / raw)
  To: Cesar Eduardo Barros; +Cc: msysgit, git

Hi,

On Sat, 28 May 2011, Cesar Eduardo Barros wrote:

> Em 28-05-2011 17:44, Johannes Schindelin escreveu:
> > On Sat, 28 May 2011, Cesar Eduardo Barros wrote:
> > > [...]
> > > @@ -1551,6 +1554,11 @@ ifdef USE_NED_ALLOCATOR
> > >          COMPAT_OBJS += compat/nedmalloc/nedmalloc.o
> > >   endif
> > >
> > > +ifdef APPLICATION_MANIFEST
> > > +	# Cannot be in LIB_OBJS because it must always be linked in
> > > +	RESOURCE_OBJS += compat/win32/resource.o
> > > +endif
> > > +
> > >   ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT
> > >   	export GIT_TEST_CMP_USE_COPIED_CONTEXT
> > >   endif
> > > [...]
> > >
> > > -git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)
> > > +git$X: git.o $(BUILTIN_OBJS) $(RESOURCE_OBJS) $(GITLIBS)
> > > [...]
> > >
> > > -git-%$X: %.o $(GITLIBS)
> > > +git-%$X: %.o $(RESOURCE_OBJS) $(GITLIBS)
> > > [...]
> >
> > Is it possible that adding the resource object to GITLIBS would reduce 
> > the patch and be "more correct", too?
> 
> I thought about it, but it felt wrong. It is not a library, it is an 
> object.

Well, a library is a collection of objects. A .a file traditionally 
contains also .o files that define both global and local variables.

Even so, let's assume for a moment that you're right and a library is a 
library of functions (which I assume that you assume), and let's ignore 
for a moment that GITLIBS provides non-functions such as inside_git_dir 
and auto_crlf. Then the approach of adding another $(RESOURCE) in exactly 
all the places where we have $(GITLIBS) is so redundant that it asks for 
future inconsistencies (somebody _will_ forget, because things still 
compile). In that case, one patch to rename GITLIBS to, say, 
COMMON_OBJECTS, and another patch to add the manifest to the common 
objects.

But as I said, IMHO GITLIBS is aptly named and should take the resource, 
too.

> Also, while adding it to GITLIBS would add the object to all the right 
> rules (in fact, I did a search for GITLIBS to find all the places to add 
> the new object to), I believe it would get the object linked twice in 
> some of the rules (the ones which do a $(filter %.o,$^) would get it 
> both from GITLIBS via the filter and from GITLIBS via $(LIBS) on the 
> command line).

Does it result in a link error? If not, it's not an issue.

Ciao,
Johannes

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [msysGit] [PATCH] Embed an application manifest on MinGW
  2011-05-28 21:19     ` Johannes Schindelin
@ 2011-05-28 21:50       ` Cesar Eduardo Barros
  0 siblings, 0 replies; 5+ messages in thread
From: Cesar Eduardo Barros @ 2011-05-28 21:50 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: msysgit, git

Em 28-05-2011 18:19, Johannes Schindelin escreveu:
> On Sat, 28 May 2011, Cesar Eduardo Barros wrote:
>> Em 28-05-2011 17:44, Johannes Schindelin escreveu:
>>> Is it possible that adding the resource object to GITLIBS would reduce
>>> the patch and be "more correct", too?
>>
>> I thought about it, but it felt wrong. It is not a library, it is an
>> object.
>
> Well, a library is a collection of objects. A .a file traditionally
> contains also .o files that define both global and local variables.

It is just a question of names: *LIBS is a list of libraries, *OBJS is a 
list of object files. It feels wrong to add something we call an object 
to something which is a list of things we call libraries. Yes, it is a 
weak argument, but it is the reason it felt wrong to me.

> Even so, let's assume for a moment that you're right and a library is a
> library of functions (which I assume that you assume), and let's ignore
> for a moment that GITLIBS provides non-functions such as inside_git_dir
> and auto_crlf. Then the approach of adding another $(RESOURCE) in exactly
> all the places where we have $(GITLIBS) is so redundant that it asks for
> future inconsistencies (somebody _will_ forget, because things still
> compile). In that case, one patch to rename GITLIBS to, say,
> COMMON_OBJECTS, and another patch to add the manifest to the common
> objects.
>
> But as I said, IMHO GITLIBS is aptly named and should take the resource,
> too.

I see no big problem with it, as long as it does not link the object 
twice. Perhaps creating a new variable which includes both GITLIBS and 
RESOURCE_OBJS but is not included in LIBS (to avoid the double linking)?

>> Also, while adding it to GITLIBS would add the object to all the right
>> rules (in fact, I did a search for GITLIBS to find all the places to add
>> the new object to), I believe it would get the object linked twice in
>> some of the rules (the ones which do a $(filter %.o,$^) would get it
>> both from GITLIBS via the filter and from GITLIBS via $(LIBS) on the
>> command line).
>
> Does it result in a link error? If not, it's not an issue.

It is worse. Not only would it not result in a link error, but it also 
would silently include the manifest resource *twice*. I recall that one 
of the pages I read while researching application manifests said that 
having more than one manifest with the same ID is an error, and we 
cannot know what Windows would do in that case (I would guess either 
"log an error and abort the executable" or "log an error and completely 
ignore the manifest"). And even if it works today, we never know what 
would happen in a future version of Windows.

The resource object really needs to be linked exactly once. It is one of 
those special objects which append or prepend data to fixed sections of 
the executable just by being linked to it (like the crt*.o gcc adds 
internally when linking). With these kinds of objects, even the link 
order is relevant (order is not a problem here because only this object 
adds to the .rsrc section, and the linker puts the section at the 
correct place). In fact, I do not even know if the resource format 
allows one to link more than one resource object in the same executable.

-- 
Cesar Eduardo Barros
cesarb@cesarb.net
cesar.barros@gmail.com

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-05-28 21:50 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-28 19:58 [PATCH] Embed an application manifest on MinGW Cesar Eduardo Barros
2011-05-28 20:44 ` [msysGit] " Johannes Schindelin
2011-05-28 21:07   ` Cesar Eduardo Barros
2011-05-28 21:19     ` Johannes Schindelin
2011-05-28 21:50       ` Cesar Eduardo Barros

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).