Always add a manifest resource to perl.exe to specify the <trustInfo>
Jan Dubois [Thu, 30 Apr 2009 23:53:20 +0000 (16:53 -0700)]
settings for Windows Vista and later.  Without this setting Windows
will treat perl.exe as a legacy application and apply various
heuristics like redirecting access to protected file system areas
(like the "Program Files" folder) to the users "VirtualStore"
instead of generating a proper "permission denied" error.

For VC8 and VC9 this manifest setting is automatically generated by
the compiler/linker (together with the binding information for their
respective runtime libraries); for all other compilers we need to
embed the manifest resource explicitly in the external resource file.

This change also requests the Microsoft Common-Controls version 6.0
(themed controls introduced in Windows XP) via the dependency list
in the assembly manifest.  For VC8 and VC9 this is specified using the
/manifestdependency linker commandline option instead.

MANIFEST
win32/Makefile
win32/makefile.mk
win32/perlexe.manifest [new file with mode: 0755]
win32/perlexe.rc
win32/win32.c

index 1a7d10e..77abbd3 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -4699,6 +4699,7 @@ win32/Makefile.ce         WinCE port
 win32/makefile.mk              Win32 makefile for DMAKE (BC++, VC++ builds)
 win32/mdelete.bat              multifile delete
 win32/perlexe.ico              perlexe.ico image file
+win32/perlexe.manifest         Assembly manifest file
 win32/perlexe.rc               associated perl binary with icon
 win32/perlglob.c               Win32 port
 win32/perlhost.h               Perl "host" implementation
index 7d7b012..b184482 100644 (file)
@@ -489,7 +489,7 @@ LIBBASEFILES        = $(CRYPT_LIB) \
                oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib \
                comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib \
                netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib \
-               version.lib odbc32.lib odbccp32.lib
+               version.lib odbc32.lib odbccp32.lib comctl32.lib
 
 # The 64 bit Platform SDK compilers contain a runtime library that doesn't
 # include the buffer overrun verification code used by the /GS switch.
@@ -515,6 +515,14 @@ EXEOUT_FLAG        = -Fe
 
 CFLAGS_O       = $(CFLAGS) $(BUILDOPT)
 
+!IF "$(CCTYPE)" == "MSVC80" || "$(CCTYPE)" == "MSVC80FREE" || \
+    "$(CCTYPE)" == "MSVC90" || "$(CCTYPE)" == "MSVC90FREE"
+LINK_FLAGS     = $(LINK_FLAGS) "/manifestdependency:type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"
+!ELSE
+RSC_FLAGS      = -DINCLUDE_MANIFEST
+!ENDIF
+
+
 #################### do not edit below this line #######################
 ############# NO USER-SERVICEABLE PARTS BEYOND THIS POINT ##############
 
@@ -538,7 +546,7 @@ $(o).dll:
        $(EMBED_DLL_MANI)
 
 .rc.res:
-       $(RSC) -i.. $<
+       $(RSC) -i.. $(RSC_FLAGS) $<
 
 #
 # various targets
@@ -576,6 +584,7 @@ UNIDATAFILES         = ..\lib\unicore\Canonical.pl ..\lib\unicore\Exact.pl \
 UNIDATADIR1    = ..\lib\unicore\To
 UNIDATADIR2    = ..\lib\unicore\lib
 
+PERLEXE_MANIFEST= .\perlexe.manifest
 PERLEXE_ICO    = .\perlexe.ico
 PERLEXE_RES    = .\perlexe.res
 PERLDLL_RES    =
@@ -955,7 +964,7 @@ $(PERLSTATICLIB): Extensions_static
 <<
        $(XCOPY) $(PERLSTATICLIB) $(COREDIR)
 
-$(PERLEXE_RES): perlexe.rc $(PERLEXE_ICO)
+$(PERLEXE_RES): perlexe.rc $(PERLEXE_MANIFEST) $(PERLEXE_ICO)
 
 $(MINIMOD) : $(MINIPERL) ..\minimod.pl
        cd ..
@@ -1195,7 +1204,7 @@ distclean: realclean
        -del /f ..\lib\Config_git.pl
        -del /f bin\*.bat
        -del /f perllibst.h
-       -del /f perl.base
+       -del /f $(PERLEXE_RES) perl.base
        -cd .. && del /s *.lib *.map *.pdb *.ilk *.bs *$(o) .exists pm_to_blib ppport.h
        -cd $(EXTDIR) && del /s *.def Makefile Makefile.old
        -cd $(DISTDIR) && del /s *.def Makefile Makefile.old
index f50a18c..960589f 100644 (file)
@@ -467,7 +467,7 @@ LIBFILES    = $(CRYPT_LIB) \
                kernel32.lib user32.lib gdi32.lib winspool.lib \
                comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib \
                netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib \
-               version.lib odbc32.lib odbccp32.lib \
+               version.lib odbc32.lib odbccp32.lib comctl32.lib \
                import32.lib $(LIBC)
 
 .IF  "$(CFG)" == "Debug"
@@ -535,7 +535,7 @@ LIBFILES    = $(CRYPT_LIB) $(LIBC) \
                  -lmoldname -lkernel32 -luser32 -lgdi32 \
                  -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 \
                  -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr \
-                 -lwinmm -lversion -lodbc32 -lodbccp32
+                 -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32
 
 .IF  "$(CFG)" == "Debug"
 OPTIMIZE       = -g -O2 -DDEBUGGING
@@ -661,6 +661,14 @@ LIBOUT_FLAG        = /out:
 
 CFLAGS_O       = $(CFLAGS) $(BUILDOPT)
 
+.IF "$(CCTYPE)" == "MSVC80" || "$(CCTYPE)" == "MSVC80FREE" || \
+    "$(CCTYPE)" == "MSVC90" || "$(CCTYPE)" == "MSVC90FREE"
+LINK_FLAGS     = $(LINK_FLAGS) "/manifestdependency:type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"
+.ELSE
+RSC_FLAGS      = -DINCLUDE_MANIFEST
+.ENDIF
+
+
 # used to allow local linking flags that are not propogated into Config.pm,
 # currently unused
 #   -- BKS, 12-12-1999
@@ -717,9 +725,9 @@ $(o).dll:
 
 .rc.res:
 .IF "$(CCTYPE)" == "GCC"
-       $(RSC) --use-temp-file --include-dir=. --include-dir=.. -O COFF -i $< -o $@
+       $(RSC) --use-temp-file --include-dir=. --include-dir=.. -O COFF -D INCLUDE_MANIFEST -i $< -o $@
 .ELSE
-       $(RSC) -i.. $<
+       $(RSC) -i.. -DINCLUDE_MANIFEST $<
 .ENDIF
 
 #
@@ -750,6 +758,7 @@ UNIDATAFILES         = ..\lib\unicore\Canonical.pl ..\lib\unicore\Exact.pl \
 UNIDATADIR1    = ..\lib\unicore\To
 UNIDATADIR2    = ..\lib\unicore\lib
 
+PERLEXE_MANIFEST= .\perlexe.manifest
 PERLEXE_ICO    = .\perlexe.ico
 PERLEXE_RES    = .\perlexe.res
 PERLDLL_RES    =
@@ -1298,7 +1307,7 @@ $(PERLSTATICLIB): Extensions_static
 .ENDIF
        $(XCOPY) $(PERLSTATICLIB) $(COREDIR)
 
-$(PERLEXE_RES): perlexe.rc $(PERLEXE_ICO)
+$(PERLEXE_RES): perlexe.rc $(PERLEXE_MANIFEST) $(PERLEXE_ICO)
 
 $(MINIMOD) : $(MINIPERL) ..\minimod.pl
        cd .. && miniperl minimod.pl > lib\ExtUtils\Miniperl.pm
@@ -1568,7 +1577,7 @@ distclean: realclean
        -del /f ..\lib\Config_git.pl
        -del /f bin\*.bat
        -del /f perllibst.h
-       -del /f perl.base
+       -del /f $(PERLEXE_RES) perl.base
        -cd .. && del /s *$(a) *.map *.pdb *.ilk *.tds *.bs *$(o) .exists pm_to_blib ppport.h
        -cd $(EXTDIR) && del /s *.def Makefile Makefile.old
        -cd $(DISTDIR) && del /s *.def Makefile Makefile.old
diff --git a/win32/perlexe.manifest b/win32/perlexe.manifest
new file mode 100755 (executable)
index 0000000..24ee19d
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+    <assemblyIdentity version="0.0.0.0" name="Perl" type="Win32" />
+    <description>Perl</description>
+    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+        <security>
+            <requestedPrivileges>
+                <requestedExecutionLevel level="asInvoker" uiAccess="false" />
+            </requestedPrivileges>
+        </security>
+    </trustInfo>
+    <dependency>
+        <dependentAssembly>
+            <assemblyIdentity type="Win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0"
+                              processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />
+        </dependentAssembly>
+    </dependency>
+</assembly>
index 627b857..c227978 100644 (file)
@@ -1 +1,8 @@
 PERLEXE            ICON    perlexe.ico
+
+#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
+#define RT_MANIFEST 24
+
+#ifdef INCLUDE_MANIFEST
+CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "perlexe.manifest"
+#endif
index 050c50c..d583087 100644 (file)
@@ -22,6 +22,7 @@
 #  define WC_NO_BEST_FIT_CHARS 0x00000400 /* requires Windows 2000 or later */
 #endif
 #include <winnt.h>
+#include <commctrl.h>
 #include <tlhelp32.h>
 #include <io.h>
 #include <signal.h>
@@ -4800,6 +4801,16 @@ Perl_win32_init(int *argcp, char ***argvp)
 {
     HMODULE module;
 
+    /* When the manifest resource requests Common-Controls v6 then
+     * user32.dll no longer registers all the Windows classes used for
+     * standard controls but leaves some of them to be registered by
+     * comctl32.dll.  InitCommonControls() doesn't do anything but calling
+     * it makes sure comctl32.dll gets loaded into the process and registers
+     * the standard control classes.  Without this even normal Windows APIs
+     * like MessageBox() can fail under some versions of Windows XP.
+     */
+    InitCommonControls();
+
 #ifdef SET_INVALID_PARAMETER_HANDLER
     _invalid_parameter_handler oldHandler, newHandler;
     newHandler = my_invalid_parameter_handler;