{"thread":{"id":"27493","subject":"[PATCH] Embed an application manifest on MinGW","startedAt":"2011-05-28T19:58:27Z","lastAt":"2011-05-28T21:50:07Z","messageCount":5,"participants":["Cesar Eduardo Barros","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"168924","messageId":"1306612707-29748-1-git-send-email-cesarb@cesarb.net","threadId":"27493","inReplyTo":null,"subject":"[PATCH] Embed an application manifest on MinGW","fromName":"Cesar Eduardo Barros","fromEmail":"cesarb@cesarb.net","sentAt":"2011-05-28T19:58:27Z","receivedAt":"2011-05-28T19:58:27Z","isPatch":true,"sender":{"key":"cesarb@cesarb.net","avatar":"https://avatars.githubusercontent.com/u/31324?v=4"},"body":"On Windows Vista, not having an application manifest with a\nrequestedExecutionLevel can cause several kinds of confusing behavior.\n\nThe first and more obvious is Installer Detection, where sometimes\nWindows decides (by looking at things like the file name and even\nsequences of bytes within the executable) that an executable is an\ninstaller and should run elevated (causing the well-known popup dialog\nto appear). On git, this happens for executables with names containing\n\"patch\" or \"update\".\n\nThe second and more confusing is File Virtualization. With it, writes to\nsome files which should fail are instead redirected to somewhere else,\nand reads to files might return different contents if a previous write\nwas redirected. Even more confusing, not all writes are redirected; I\nrecall reading somewhere that for instance writes to .exe files will\nfail instead of redirecting.\n\nNeedless to say, git wants none of that. Not only that, but File\nVirtualization has been blamed for dramatic slowdowns in git (see for\ninstance http://code.google.com/p/msysgit/issues/detail?id=320).\n\nThere are two ways to turn off these annoyances. Either you embed an\napplication manifest within all your executables, or you add an external\nmanifest (a file with the same name followed by .manifest) to all your\nexecutables. Since for git some executables are copied (or hardlinked)\nwith several names, it is simpler and more robust to embed an internal\nmanifest.\n\nA recent enough MSVC compiler should already embed a working internal\nmanifest, but for mingw you have to do so by hand.\n\nVery lightly tested on Wine, where like on Windows XP it should not make\nany difference.\n\nReferences:\n  - New UAC Technologies for Windows Vista\n    http://msdn.microsoft.com/en-us/library/bb756960.aspx\n  - Create and Embed an Application Manifest (UAC)\n    http://msdn.microsoft.com/en-us/library/bb756929.aspx\n\nSigned-off-by: Cesar Eduardo Barros <cesarb@cesarb.net>\n---\n Makefile                  |   29 +++++++++++++++++++++--------\n compat/win32/git.manifest |   11 +++++++++++\n compat/win32/resource.rc  |    1 +\n 3 files changed, 33 insertions(+), 8 deletions(-)\n create mode 100644 compat/win32/git.manifest\n create mode 100644 compat/win32/resource.rc\n\ndiff --git a/Makefile b/Makefile\nindex dec4a7f..3dbcdfb 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -323,6 +323,7 @@ XGETTEXT = xgettext\n PTHREAD_LIBS = -lpthread\n PTHREAD_CFLAGS =\n GCOV = gcov\n+WINDRES = windres\n \n export TCL_PATH TCLTK_PATH\n \n@@ -343,6 +344,7 @@ BUILTIN_OBJS =\n BUILT_INS =\n COMPAT_CFLAGS =\n COMPAT_OBJS =\n+RESOURCE_OBJS =\n EXTRA_CPPFLAGS =\n LIB_H =\n LIB_OBJS =\n@@ -1174,6 +1176,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_INET_PTON = YesPlease\n \tNO_INET_NTOP = YesPlease\n \tNO_POSIX_GOODIES = UnfortunatelyYes\n+\tAPPLICATION_MANIFEST = YesPlease\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/win32\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/winansi.o \\\n@@ -1551,6 +1554,11 @@ ifdef USE_NED_ALLOCATOR\n        COMPAT_OBJS += compat/nedmalloc/nedmalloc.o\n endif\n \n+ifdef APPLICATION_MANIFEST\n+\t# Cannot be in LIB_OBJS because it must always be linked in\n+\tRESOURCE_OBJS += compat/win32/resource.o\n+endif\n+\n ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT\n \texport GIT_TEST_CMP_USE_COPIED_CONTEXT\n endif\n@@ -1586,6 +1594,7 @@ ifndef V\n \tQUIET_LNCP     = @echo '   ' LN/CP $@;\n \tQUIET_XGETTEXT = @echo '   ' XGETTEXT $@;\n \tQUIET_GCOV     = @echo '   ' GCOV $@;\n+\tQUIET_WINDRES  = @echo '   ' RC $@;\n \tQUIET_SP       = @echo '   ' SP $<;\n \tQUIET_SUBDIR0  = +@subdir=\n \tQUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \\\n@@ -1685,9 +1694,9 @@ git.o: common-cmds.h\n git.sp git.s git.o: EXTRA_CPPFLAGS = -DGIT_VERSION='\"$(GIT_VERSION)\"' \\\n \t'-DGIT_HTML_PATH=\"$(htmldir_SQ)\"'\n \n-git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)\n+git$X: git.o $(BUILTIN_OBJS) $(RESOURCE_OBJS) $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \\\n-\t\t$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)\n+\t\t$(BUILTIN_OBJS) $(RESOURCE_OBJS) $(ALL_LDFLAGS) $(LIBS)\n \n help.sp help.o: common-cmds.h\n \n@@ -2011,17 +2020,17 @@ compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \\\n \t-DNDEBUG -DOVERRIDE_STRDUP -DREPLACE_SYSTEM_ALLOCATOR\n endif\n \n-git-%$X: %.o $(GITLIBS)\n+git-%$X: %.o $(RESOURCE_OBJS) $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)\n \n-git-imap-send$X: imap-send.o $(GITLIBS)\n+git-imap-send$X: imap-send.o $(RESOURCE_OBJS) $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n \t\t$(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)\n \n-git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)\n+git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(RESOURCE_OBJS) $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n \t\t$(LIBS) $(CURL_LIBCURL)\n-git-http-push$X: revision.o http.o http-push.o $(GITLIBS)\n+git-http-push$X: revision.o http.o http-push.o $(RESOURCE_OBJS) $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n \t\t$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)\n \n@@ -2031,10 +2040,14 @@ $(REMOTE_CURL_ALIASES): $(REMOTE_CURL_PRIMARY)\n \tln -s $< $@ 2>/dev/null || \\\n \tcp $< $@\n \n-$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(GITLIBS)\n+$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(RESOURCE_OBJS) $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \\\n \t\t$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)\n \n+%.o: %.rc\n+\t$(QUIET_WINDRES)$(WINDRES) $< $@\n+compat/win32/resource.o: compat/win32/git.manifest\n+\n $(LIB_FILE): $(LIB_OBJS)\n \t$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)\n \n@@ -2167,7 +2180,7 @@ test-svn-fe$X: vcs-svn/lib.a\n \n .PRECIOUS: $(TEST_OBJS)\n \n-test-%$X: test-%.o $(GITLIBS)\n+test-%$X: test-%.o $(RESOURCE_OBJS) $(GITLIBS)\n \t$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS)\n \n check-sha1:: test-sha1$X\ndiff --git a/compat/win32/git.manifest b/compat/win32/git.manifest\nnew file mode 100644\nindex 0000000..a82605c\n--- /dev/null\n+++ b/compat/win32/git.manifest\n@@ -0,0 +1,11 @@\n+<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n+<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n+\t<assemblyIdentity type=\"win32\" name=\"Git\" processorArchitecture=\"x86\" version=\"0.0.0.0\" />\n+\t<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v2\">\n+\t\t<security>\n+\t\t\t<requestedPrivileges>\n+\t\t\t\t<requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\" />\n+\t\t\t</requestedPrivileges>\n+\t\t</security>\n+\t</trustInfo>\n+</assembly>\ndiff --git a/compat/win32/resource.rc b/compat/win32/resource.rc\nnew file mode 100644\nindex 0000000..c2bf4a6\n--- /dev/null\n+++ b/compat/win32/resource.rc\n@@ -0,0 +1 @@\n+1 24 \"git.manifest\"\n-- \n1.7.4.4\n"},{"id":"168927","messageId":"alpine.DEB.1.00.1105282241510.11411@bonsai2","threadId":"27493","inReplyTo":"1306612707-29748-1-git-send-email-cesarb@cesarb.net","subject":"Re: [msysGit] [PATCH] Embed an application manifest on MinGW","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2011-05-28T20:44:03Z","receivedAt":"2011-05-28T20:44:03Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 28 May 2011, Cesar Eduardo Barros wrote:\n\n> [...]\n> @@ -1551,6 +1554,11 @@ ifdef USE_NED_ALLOCATOR\n>         COMPAT_OBJS += compat/nedmalloc/nedmalloc.o\n>  endif\n>  \n> +ifdef APPLICATION_MANIFEST\n> +\t# Cannot be in LIB_OBJS because it must always be linked in\n> +\tRESOURCE_OBJS += compat/win32/resource.o\n> +endif\n> +\n>  ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT\n>  \texport GIT_TEST_CMP_USE_COPIED_CONTEXT\n>  endif\n> [...]\n>  \n> -git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)\n> +git$X: git.o $(BUILTIN_OBJS) $(RESOURCE_OBJS) $(GITLIBS)\n> [...]\n>  \n> -git-%$X: %.o $(GITLIBS)\n> +git-%$X: %.o $(RESOURCE_OBJS) $(GITLIBS)\n> [...]\n>  \n> -git-imap-send$X: imap-send.o $(GITLIBS)\n> +git-imap-send$X: imap-send.o $(RESOURCE_OBJS) $(GITLIBS)\n> [...]\n>  \n> -git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)\n> +git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(RESOURCE_OBJS) $(GITLIBS)\n> [...]\n> -git-http-push$X: revision.o http.o http-push.o $(GITLIBS)\n> +git-http-push$X: revision.o http.o http-push.o $(RESOURCE_OBJS) $(GITLIBS)\n> [...]\n>  \n> -$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(GITLIBS)\n> +$(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o $(RESOURCE_OBJS) $(GITLIBS)\n> [...]\n>  \n> -test-%$X: test-%.o $(GITLIBS)\n> +test-%$X: test-%.o $(RESOURCE_OBJS) $(GITLIBS)\n> [...]\n\nIs it possible that adding the resource object to GITLIBS would reduce the \npatch and be \"more correct\", too?\n\nThanks,\nJohannes\n"},{"id":"168929","messageId":"4DE16418.4020002@cesarb.net","threadId":"27493","inReplyTo":"alpine.DEB.1.00.1105282241510.11411@bonsai2","subject":"Re: [msysGit] [PATCH] Embed an application manifest on MinGW","fromName":"Cesar Eduardo Barros","fromEmail":"cesarb@cesarb.net","sentAt":"2011-05-28T21:07:36Z","receivedAt":"2011-05-28T21:07:36Z","isPatch":true,"sender":{"key":"cesarb@cesarb.net","avatar":"https://avatars.githubusercontent.com/u/31324?v=4"},"body":"Em 28-05-2011 17:44, Johannes Schindelin escreveu:\n> On Sat, 28 May 2011, Cesar Eduardo Barros wrote:\n>> [...]\n>> @@ -1551,6 +1554,11 @@ ifdef USE_NED_ALLOCATOR\n>>          COMPAT_OBJS += compat/nedmalloc/nedmalloc.o\n>>   endif\n>>\n>> +ifdef APPLICATION_MANIFEST\n>> +\t# Cannot be in LIB_OBJS because it must always be linked in\n>> +\tRESOURCE_OBJS += compat/win32/resource.o\n>> +endif\n>> +\n>>   ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT\n>>   \texport GIT_TEST_CMP_USE_COPIED_CONTEXT\n>>   endif\n>> [...]\n>>\n>> -git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)\n>> +git$X: git.o $(BUILTIN_OBJS) $(RESOURCE_OBJS) $(GITLIBS)\n>> [...]\n>>\n>> -git-%$X: %.o $(GITLIBS)\n>> +git-%$X: %.o $(RESOURCE_OBJS) $(GITLIBS)\n>> [...]\n>\n> Is it possible that adding the resource object to GITLIBS would reduce the\n> patch and be \"more correct\", too?\n\nI thought about it, but it felt wrong. It is not a library, it is an object.\n\nAlso, while adding it to GITLIBS would add the object to all the right \nrules (in fact, I did a search for GITLIBS to find all the places to add \nthe new object to), I believe it would get the object linked twice in \nsome of the rules (the ones which do a $(filter %.o,$^) would get it \nboth from GITLIBS via the filter and from GITLIBS via $(LIBS) on the \ncommand line).\n\n-- \nCesar Eduardo Barros\ncesarb@cesarb.net\ncesar.barros@gmail.com\n"},{"id":"168930","messageId":"alpine.DEB.1.00.1105282311220.11411@bonsai2","threadId":"27493","inReplyTo":"4DE16418.4020002@cesarb.net","subject":"Re: [msysGit] [PATCH] Embed an application manifest on MinGW","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2011-05-28T21:19:06Z","receivedAt":"2011-05-28T21:19:06Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 28 May 2011, Cesar Eduardo Barros wrote:\n\n> Em 28-05-2011 17:44, Johannes Schindelin escreveu:\n> > On Sat, 28 May 2011, Cesar Eduardo Barros wrote:\n> > > [...]\n> > > @@ -1551,6 +1554,11 @@ ifdef USE_NED_ALLOCATOR\n> > >          COMPAT_OBJS += compat/nedmalloc/nedmalloc.o\n> > >   endif\n> > >\n> > > +ifdef APPLICATION_MANIFEST\n> > > +\t# Cannot be in LIB_OBJS because it must always be linked in\n> > > +\tRESOURCE_OBJS += compat/win32/resource.o\n> > > +endif\n> > > +\n> > >   ifdef GIT_TEST_CMP_USE_COPIED_CONTEXT\n> > >   \texport GIT_TEST_CMP_USE_COPIED_CONTEXT\n> > >   endif\n> > > [...]\n> > >\n> > > -git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)\n> > > +git$X: git.o $(BUILTIN_OBJS) $(RESOURCE_OBJS) $(GITLIBS)\n> > > [...]\n> > >\n> > > -git-%$X: %.o $(GITLIBS)\n> > > +git-%$X: %.o $(RESOURCE_OBJS) $(GITLIBS)\n> > > [...]\n> >\n> > Is it possible that adding the resource object to GITLIBS would reduce \n> > the patch and be \"more correct\", too?\n> \n> I thought about it, but it felt wrong. It is not a library, it is an \n> object.\n\nWell, a library is a collection of objects. A .a file traditionally \ncontains also .o files that define both global and local variables.\n\nEven so, let's assume for a moment that you're right and a library is a \nlibrary of functions (which I assume that you assume), and let's ignore \nfor a moment that GITLIBS provides non-functions such as inside_git_dir \nand auto_crlf. Then the approach of adding another $(RESOURCE) in exactly \nall the places where we have $(GITLIBS) is so redundant that it asks for \nfuture inconsistencies (somebody _will_ forget, because things still \ncompile). In that case, one patch to rename GITLIBS to, say, \nCOMMON_OBJECTS, and another patch to add the manifest to the common \nobjects.\n\nBut as I said, IMHO GITLIBS is aptly named and should take the resource, \ntoo.\n\n> Also, while adding it to GITLIBS would add the object to all the right \n> rules (in fact, I did a search for GITLIBS to find all the places to add \n> the new object to), I believe it would get the object linked twice in \n> some of the rules (the ones which do a $(filter %.o,$^) would get it \n> both from GITLIBS via the filter and from GITLIBS via $(LIBS) on the \n> command line).\n\nDoes it result in a link error? If not, it's not an issue.\n\nCiao,\nJohannes\n"},{"id":"168931","messageId":"4DE16E0F.6020807@cesarb.net","threadId":"27493","inReplyTo":"alpine.DEB.1.00.1105282311220.11411@bonsai2","subject":"Re: [msysGit] [PATCH] Embed an application manifest on MinGW","fromName":"Cesar Eduardo Barros","fromEmail":"cesarb@cesarb.net","sentAt":"2011-05-28T21:50:07Z","receivedAt":"2011-05-28T21:50:07Z","isPatch":true,"sender":{"key":"cesarb@cesarb.net","avatar":"https://avatars.githubusercontent.com/u/31324?v=4"},"body":"Em 28-05-2011 18:19, Johannes Schindelin escreveu:\n> On Sat, 28 May 2011, Cesar Eduardo Barros wrote:\n>> Em 28-05-2011 17:44, Johannes Schindelin escreveu:\n>>> Is it possible that adding the resource object to GITLIBS would reduce\n>>> the patch and be \"more correct\", too?\n>>\n>> I thought about it, but it felt wrong. It is not a library, it is an\n>> object.\n>\n> Well, a library is a collection of objects. A .a file traditionally\n> contains also .o files that define both global and local variables.\n\nIt is just a question of names: *LIBS is a list of libraries, *OBJS is a \nlist of object files. It feels wrong to add something we call an object \nto something which is a list of things we call libraries. Yes, it is a \nweak argument, but it is the reason it felt wrong to me.\n\n> Even so, let's assume for a moment that you're right and a library is a\n> library of functions (which I assume that you assume), and let's ignore\n> for a moment that GITLIBS provides non-functions such as inside_git_dir\n> and auto_crlf. Then the approach of adding another $(RESOURCE) in exactly\n> all the places where we have $(GITLIBS) is so redundant that it asks for\n> future inconsistencies (somebody _will_ forget, because things still\n> compile). In that case, one patch to rename GITLIBS to, say,\n> COMMON_OBJECTS, and another patch to add the manifest to the common\n> objects.\n>\n> But as I said, IMHO GITLIBS is aptly named and should take the resource,\n> too.\n\nI see no big problem with it, as long as it does not link the object \ntwice. Perhaps creating a new variable which includes both GITLIBS and \nRESOURCE_OBJS but is not included in LIBS (to avoid the double linking)?\n\n>> Also, while adding it to GITLIBS would add the object to all the right\n>> rules (in fact, I did a search for GITLIBS to find all the places to add\n>> the new object to), I believe it would get the object linked twice in\n>> some of the rules (the ones which do a $(filter %.o,$^) would get it\n>> both from GITLIBS via the filter and from GITLIBS via $(LIBS) on the\n>> command line).\n>\n> Does it result in a link error? If not, it's not an issue.\n\nIt is worse. Not only would it not result in a link error, but it also \nwould silently include the manifest resource *twice*. I recall that one \nof the pages I read while researching application manifests said that \nhaving more than one manifest with the same ID is an error, and we \ncannot know what Windows would do in that case (I would guess either \n\"log an error and abort the executable\" or \"log an error and completely \nignore the manifest\"). And even if it works today, we never know what \nwould happen in a future version of Windows.\n\nThe resource object really needs to be linked exactly once. It is one of \nthose special objects which append or prepend data to fixed sections of \nthe executable just by being linked to it (like the crt*.o gcc adds \ninternally when linking). With these kinds of objects, even the link \norder is relevant (order is not a problem here because only this object \nadds to the .rsrc section, and the linker puts the section at the \ncorrect place). In fact, I do not even know if the resource format \nallows one to link more than one resource object in the same executable.\n\n-- \nCesar Eduardo Barros\ncesarb@cesarb.net\ncesar.barros@gmail.com\n"}]}