/*
CVSNT Automatic manifest generator
Copyright (C) 2006 Tony Hoyle and March-Hare Software Ltd
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// mkmanifest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "../../version.h"
#include <atlbase.h> // Includes CComVariant and CComBSTR.
int parse_manifest(MSXML2::IXMLDOMDocument2Ptr outDoc, const char *xml)
{
MSXML2::IXMLDOMDocument2Ptr doc;
CComVariant varNodeType;
HRESULT hr;
varNodeType = NODE_ELEMENT; // MSXML2::NODE_ELEMENT
hr = doc.CreateInstance("Msxml2.DOMDocument.6.0");
if (!SUCCEEDED(hr))
{
// the most common thing here is "invalid class string"
hr = doc.CreateInstance("Msxml2.DOMDocument.5.0");
if (!SUCCEEDED(hr))
{
hr = doc.CreateInstance("Msxml2.DOMDocument.4.0");
if (!SUCCEEDED(hr))
{
return -1;
}
}
}
if(!doc->loadXML(xml))
return -1;
doc->setProperty("SelectionLanguage","XPath");
doc->setProperty("SelectionNamespaces", "xmlns:ns='urn:schemas-microsoft-com:asm.v1'");
_bstr_t version,name,type,processor,language;
MSXML2::IXMLDOMNodePtr node,val;
node = doc->selectSingleNode("/ns:assembly/ns:assemblyIdentity");
if(node==NULL)
return -1;
val = node->attributes->getNamedItem("version");
if(val) version = val->text;
else return -1;
val = node->attributes->getNamedItem("name");
if(val) name = val->text;
else return -1;
val = node->attributes->getNamedItem("processorArchitecture");
if(val) processor = val->text;
#ifdef _WIN64
else processor="amd64";
#else
else processor="x86";
#endif
val = node->attributes->getNamedItem("language"); // No examples of this so this may be wrong
if(val) language = val->text;
else language="*";
val = node->attributes->getNamedItem("type");
if(val) type = val->text;
else type="Win32";
node = outDoc->selectSingleNode("/ns:assembly");
val = outDoc->createNode(varNodeType,"dependency","urn:schemas-microsoft-com:asm.v1");
node->appendChild(val);
node = val;
MSXML2::IXMLDOMNodePtr dep = outDoc->createNode(varNodeType,"dependentAssembly","urn:schemas-microsoft-com:asm.v1");
MSXML2::IXMLDOMNodePtr iden = outDoc->createNode(varNodeType,"assemblyIdentity","urn:schemas-microsoft-com:asm.v1");
node->appendChild(dep);
dep->appendChild(iden);
val = outDoc->createAttribute("version");
val->text=version;
iden->attributes->setNamedItem(val);
val = outDoc->createAttribute("type");
val->text=type;
iden->attributes->setNamedItem(val);
val = outDoc->createAttribute("name");
val->text=name;
iden->attributes->setNamedItem(val);
val = outDoc->createAttribute("processorArchitecture");
val->text=processor;
iden->attributes->setNamedItem(val);
val = outDoc->createAttribute("language");
val->text=language;
iden->attributes->setNamedItem(val);
return 0;
}
static WORD g_wManifestLanguage=MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
BOOL CALLBACK EnumResLangProc(
HANDLE hModule,
LPCTSTR lpszType,
LPCTSTR lpszName,
WORD wIDLanguage,
LONG_PTR lParam)
{
g_wManifestLanguage=wIDLanguage;
return FALSE;
}
void mkmanifest_help(void)
{
printf("cvsnt manifest patcher "CVSNT_PRODUCTVERSION_STRING"\n");
printf("usage: mkmanifest [-v version] [-d] [-r] [-q] [-a] [-u] [-P searchpath] [-d] <library>\n");
printf(" -d verbose mode (implies -a -u)\n");
printf(" -a create an ascii manifest file\n");
printf(" -u create a unicode manifest file (with BOM)\n");
printf(" -q quiet and do not prompt for a key at end\n");
printf(" -Q really quiet and do not prompt for a key at end\n");
printf(" **** experimental options:\n");
printf(" -r if there is no version block in the resource segment attempt to add one\n");
printf(" -f force mkmanifest to add a manifest with no version block\n");
}
int main(int argc, char* argv[])
{
LOADED_IMAGE *loaded_image;
char szPath[4096];
std::string version,path;
bool setversion=false;
bool debug=false;
bool addversion=false;
bool asciimanifest=false;
bool forceadd=false;
bool unicodemanifest=false;
bool donotstop=false;
bool reallyquiet=false;
HRESULT hr;
hr = CoInitialize(NULL);
if (hr != S_OK )
return -1;
MSXML2::IXMLDOMDocument2Ptr doc;
hr = doc.CreateInstance("Msxml2.DOMDocument.6.0");
if (!SUCCEEDED(hr))
{
// the most common thing here is "invalid class string"
hr = doc.CreateInstance("Msxml2.DOMDocument.5.0");
if (!SUCCEEDED(hr))
{
hr = doc.CreateInstance("Msxml2.DOMDocument.4.0");
if (!SUCCEEDED(hr))
{
return -1;
}
}
}
version=CVSNT_PRODUCTVERSION_SHORT;
path="..;d:\\cvsbin\\sysfiles;d:\\cvsbin;..\\cvsdeps\\sysfiles;c:\\Program Files\\CVSNT;c:\\Program Files\\CVS Suite\\CVSNT;c:\\Program Files\\CVSNT\\sysfiles;c:\\Program Files\\CVS Suite\\CVSNT\\sysfiles";
debug=false;
while(argc>1 && argv[1][0]=='-')
{
switch(argv[1][1])
{
case 'v':
version = argv[2];
argv++;
argc--;
setversion=true;
break;
case 'P':
path = argv[2];
argv++;
argc--;
break;
case 'a':
asciimanifest = true;
break;
case 'f':
forceadd = true;
break;
case 'u':
unicodemanifest = true;
break;
case 'd':
debug = true;
break;
case 'q':
donotstop = true;
break;
case 'Q':
reallyquiet = true;
break;
case 'r':
addversion = true;
break;
default:
mkmanifest_help();
return -1;
}
argv++;
argc--;
}
if(argc<2)
{
mkmanifest_help();
return -1;
}
HMODULE hRes = LoadLibraryEx(argv[1],NULL,DONT_RESOLVE_DLL_REFERENCES);
if(!hRes)
{
printf("Couldn't load image!\n");
return 0;
}
GetModuleFileName(hRes, szPath, sizeof(szPath));
if(debug)
printf("Generating manifest for version %s of %s\n",version.c_str(),szPath);
*strrchr(szPath,'\\')='\0';
SetCurrentDirectory(szPath);
strcpy(szPath,path.c_str());
strcat(szPath,";");
GetEnvironmentVariable("Path",szPath+strlen(szPath),(DWORD)(sizeof(path)-strlen(szPath)));
SetEnvironmentVariable("Path",szPath);
HRSRC hRsrc = FindResource(hRes,MAKEINTRESOURCE(1),RT_MANIFEST);
if(hRsrc)
{
if(debug)
printf("Found the manifest resource\n");
EnumResourceLanguages(hRes,RT_MANIFEST,MAKEINTRESOURCE(1),(ENUMRESLANGPROC)EnumResLangProc,NULL);
LPVOID pRsrc = LoadResource(hRes, hRsrc);
DWORD dwLen = SizeofResource(hRes, hRsrc);
DWORD dwOldProtect;
VirtualProtect(pRsrc,dwLen+1,PAGE_READWRITE,&dwOldProtect);
((LPBYTE)pRsrc)[dwLen]='\0'; // This is cheating but we don't care since this is the only data we need
if(doc->loadXML((const char *)pRsrc))
{
doc->setProperty("SelectionLanguage","XPath");
doc->setProperty("SelectionNamespaces", "xmlns='urn:schemas-microsoft-com:asm.v1' xmlns:ns='urn:schemas-microsoft-com:asm.v1'");
}
else
{
const char *_xml="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n"
"<assemblyIdentity version=\"1.0.0.0\" processorArchitecture=\"*\" name=\"\" type=\"win32\"/>\n"
"</assembly>\n";
if(doc->loadXML(_xml))
{
doc->setProperty("SelectionLanguage","XPath");
doc->setProperty("SelectionNamespaces", "xmlns='urn:schemas-microsoft-com:asm.v1' xmlns:ns='urn:schemas-microsoft-com:asm.v1'");
}
}
FreeResource(hRsrc);
}
else
{
if(debug)
printf("No manifest resource in this object - make our own\n");
const char *_xml="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n"
"<assemblyIdentity version=\"1.0.0.0\" processorArchitecture=\"*\" name=\"\" type=\"win32\"/>\n"
"</assembly>\n";
if(doc->loadXML(_xml))
{
doc->setProperty("SelectionLanguage","XPath");
doc->setProperty("SelectionNamespaces", "xmlns='urn:schemas-microsoft-com:asm.v1' xmlns:ns='urn:schemas-microsoft-com:asm.v1'");
}
}
HRSRC hRsrc_v = FindResource(hRes,MAKEINTRESOURCE(VS_VERSION_INFO),RT_VERSION);
if(hRsrc_v)
{
LPVOID pRsrc = LoadResource(hRes, hRsrc_v);
// something here.. updating versioninfo is even harder than updating the manifests!
if (pRsrc!=NULL)
{
if(debug)
printf("The version resource is loaded \n");
LPVOID pBlock = LockResource(pRsrc);
if (pBlock != NULL)
{
VS_FIXEDFILEINFO fixedinfo;
const char csEntry[]="FileVersion\0";
char csRet[4096];
DWORD dwLen,langD;
BOOL retVal;
LPVOID retbuffer=NULL;
static char szSubBlock[256];
sprintf(szSubBlock, "\\");
retVal = VerQueryValue(pBlock, szSubBlock, &retbuffer, (UINT *)&dwLen);
if (retVal && dwLen==sizeof(fixedinfo))
{
memcpy(&fixedinfo,retbuffer,sizeof(fixedinfo));
if ((!reallyquiet) || (debug))
{
printf("FileVersion = %d, %d, %d, %d\n",
(fixedinfo.dwFileVersionMS&0xffff0000)>>16,
fixedinfo.dwFileVersionMS&0xffff,
(fixedinfo.dwFileVersionLS&0xffff0000)>>16,
fixedinfo.dwFileVersionLS&0xffff);
printf("ProductVersion = %d, %d, %d, %d\n",
(fixedinfo.dwProductVersionMS&0xffff0000)>>16,
fixedinfo.dwProductVersionMS&0xffff,
(fixedinfo.dwProductVersionLS&0xffff0000)>>16,
fixedinfo.dwProductVersionLS&0xffff);
if (debug)
{
printf("FileOS = 0x%x\n",fixedinfo.dwFileOS);
printf("FileType = 0x%x\n",fixedinfo.dwFileType);
printf("FielSubtype = 0x%x\n",fixedinfo.dwFileSubtype);
}
}
}
sprintf(szSubBlock, "\\VarFileInfo\\Translation");
retVal = VerQueryValue(pBlock, szSubBlock, &retbuffer, (UINT *)&dwLen);
if (retVal && dwLen==4)
{
memcpy(&langD, retbuffer, 4);
sprintf(szSubBlock, "\\StringFileInfo\\%02X%02X%02X%02X\\%s",
(langD & 0xff00)>>8, langD & 0xff,(langD & 0xff000000)>>24,
(langD & 0xff0000)>>16, csEntry);
}
else
sprintf(szSubBlock, "\\StringFileInfo\\%04X04B0\\%s",
GetUserDefaultLangID(), csEntry);
dwLen=0;
if (VerQueryValue(pBlock, szSubBlock, &retbuffer, (UINT *)&dwLen))
strcpy(csRet, (char *)retbuffer);
else
{
if (debug)
printf("VerQueryValue returned error\n");
}
UnlockResource(pRsrc);
if (debug)
printf("VerQueryValue %s = %s\n",szSubBlock,(char *)csRet);
}
}
FreeResource(hRsrc_v);
}
else
{
if ((!addversion)&&(!forceadd))
{
printf("The file does not contain any version resources, cannot add a manifest!\n");
printf("Use the -r option if you want to attempt adding version resources.\n");
printf("or use the -f option to force adding a manifest with no version resources.\n");
return -1;
}
else
if (forceadd)
{
printf("The file does not contain any resources, adding a manifest will probably break it!\n");
}
else
{
// attempt to add a version block!
VS_FIXEDFILEINFO fixedinfo;
size_t lenpath;
char szPathFile[4096];
GetModuleFileName(hRes, szPathFile, sizeof(szPathFile));
if (setversion)
{
printf("Cannot combine -v and -r parameters!\n");
return -1;
}
if (debug)
printf("Attempt to add a version resource.\n");
ZeroMemory(&fixedinfo,sizeof(fixedinfo));
// CVSNT_PRODUCT_MAJOR,
// CVSNT_PRODUCT_MINOR,
// CVSNT_PRODUCT_PATCHLEVEL:
// CVSNT_PRODUCT_BUILD:
fixedinfo.dwFileVersionMS = CVSNT_PRODUCT_MAJOR<<16;
fixedinfo.dwFileVersionMS += CVSNT_PRODUCT_MINOR;
fixedinfo.dwFileVersionLS = CVSNT_PRODUCT_PATCHLEVEL<<16;
fixedinfo.dwFileVersionLS += CVSNT_PRODUCT_BUILD;
if (!reallyquiet)
{
printf("FileVersion = %d, %d, %d, %d\n",
(fixedinfo.dwFileVersionMS&0xffff0000)>>16,
fixedinfo.dwFileVersionMS&0xffff,
(fixedinfo.dwFileVersionLS&0xffff0000)>>16,
fixedinfo.dwFileVersionLS&0xffff);
}
fixedinfo.dwProductVersionMS = CVSNT_PRODUCT_MAJOR<<16;
fixedinfo.dwProductVersionMS += CVSNT_PRODUCT_MINOR;
fixedinfo.dwProductVersionLS = CVSNT_PRODUCT_PATCHLEVEL<<16;
if (!reallyquiet)
{
printf("ProductVersion = %d, %d, %d, %d\n",
(fixedinfo.dwProductVersionMS&0xffff0000)>>16,
fixedinfo.dwProductVersionMS&0xffff,
(fixedinfo.dwProductVersionLS&0xffff0000)>>16,
fixedinfo.dwProductVersionLS&0xffff);
}
fixedinfo.dwFileFlags = 0x1;
fixedinfo.dwFileFlagsMask = 0x17;
fixedinfo.dwFileOS = 0x4; // VOS_WINDOWS32
if (debug)
{
printf("FileOS = 0x%x\n",fixedinfo.dwFileOS);
printf("FileType = 0x%x\n",fixedinfo.dwFileType);
printf("FielSubtype = 0x%x\n",fixedinfo.dwFileSubtype);
}
lenpath=strlen(argv[1]);
if (debug)
printf("the file suffiix is %s\n",&argv[1][lenpath-4]);
if (stricmp(&argv[1][lenpath-4],".dll")==0)
fixedinfo.dwFileType = 0x2; // VFT_DLL
else
fixedinfo.dwFileType = 0x1; // VFT_APP
fixedinfo.dwFileSubtype = 0; // VFT2_UNKNOWN
FreeLibrary(hRes);
HANDLE hUpdate1 = BeginUpdateResource(argv[1],TRUE);
if(!hUpdate1)
{
printf("BeginUpdateResource (version) failed!!!\n");
return -1;
}
if(!UpdateResource(hUpdate1,RT_VERSION,"",g_wManifestLanguage,(LPVOID)&fixedinfo,sizeof(fixedinfo)))
{
printf("UpdateResource (version) failed!!\n");
return -1;
}
if(!EndUpdateResource(hUpdate1, FALSE))
{
printf("EndUpdateResource (version) failed!!\n");
return -1;
}
hRes = LoadLibraryEx(argv[1],NULL,DONT_RESOLVE_DLL_REFERENCES);
if (hRes==NULL)
return -1;
}
}
loaded_image=ImageLoad(argv[1],NULL);
if(!loaded_image)
{
printf("Couldn't load image!");
return 0;
}
DWORD dwSize;
PBYTE pDllName;
PIMAGE_IMPORT_DESCRIPTOR pimage_import_descriptor= (PIMAGE_IMPORT_DESCRIPTOR)
ImageDirectoryEntryToData(loaded_image->MappedAddress,FALSE,IMAGE_DIRECTORY_ENTRY_IMPORT,&dwSize);
if(debug) printf("Dependencies:\n");
while(pimage_import_descriptor->Name!=0)
{
pDllName = (PBYTE)ImageRvaToVa(loaded_image->FileHeader,loaded_image->MappedAddress,pimage_import_descriptor->Name,NULL);
HMODULE hRes2 = LoadLibraryEx((LPCSTR)pDllName,NULL,DONT_RESOLVE_DLL_REFERENCES);
if(hRes2)
{
GetModuleFileName(hRes2, szPath, sizeof(szPath));
HRSRC hRsrc = FindResource(hRes2,MAKEINTRESOURCE(1),RT_MANIFEST);
if(hRsrc)
{
LPVOID pRsrc = LoadResource(hRes2, hRsrc);
DWORD dwLen = SizeofResource(hRes2, hRsrc);
DWORD dwOldProtect;
VirtualProtect(pRsrc,dwLen+1,PAGE_READWRITE,&dwOldProtect);
((LPBYTE)pRsrc)[dwLen]='\0'; // This is cheating but we don't care since this is the only data we need
if(debug) printf(" %s (manifest)\n",szPath);
parse_manifest(doc, (const char *)pRsrc);
FreeResource(hRsrc);
}
else
if(debug) printf(" %s\n",szPath);
FreeLibrary(hRes2);
}
pimage_import_descriptor++;
}
ImgDelayDescr *pimage_delay_descriptor= (ImgDelayDescr*)
ImageDirectoryEntryToData(loaded_image->MappedAddress,FALSE,IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,&dwSize);
#if (DELAYLOAD_VERSION >= 0x0200) || (_DELAY_IMP_VER > 1)
if(debug) printf("Delayload dependencies (delayload version >= 0x0200 or delay imp ver >1):\n");
while(pimage_delay_descriptor && pimage_delay_descriptor->rvaDLLName!=0)
#else
if(debug) printf("Delayload dependencies (delayload version < 0x0200 and delay imp ver <1):\n");
while(pimage_delay_descriptor && pimage_delay_descriptor->szName!=NULL)
#endif
{
#if (DELAYLOAD_VERSION >= 0x0200) || (_DELAY_IMP_VER > 1)
pDllName = (PBYTE)ImageRvaToVa(loaded_image->FileHeader,loaded_image->MappedAddress,pimage_delay_descriptor->rvaDLLName,NULL);
#else
pDllName = (PBYTE)pimage_delay_descriptor->szName;
#endif
HMODULE hRes3 = LoadLibraryEx((LPCSTR)pDllName,NULL,DONT_RESOLVE_DLL_REFERENCES);
if(hRes3)
{
GetModuleFileName(hRes3, szPath, sizeof(szPath));
HRSRC hRsrc = FindResource(hRes3,MAKEINTRESOURCE(1),RT_MANIFEST);
if(hRsrc)
{
LPVOID pRsrc = LoadResource(hRes3, hRsrc);
DWORD dwLen = SizeofResource(hRes3, hRsrc);
DWORD dwOldProtect;
VirtualProtect(pRsrc,dwLen+1,PAGE_READWRITE,&dwOldProtect);
((LPBYTE)pRsrc)[dwLen]='\0'; // This is cheating but we don't care since this is the only data we need
if(debug) printf(" %s (manifest)\n",szPath);
parse_manifest(doc, (const char *)pRsrc);
FreeResource(hRsrc);
}
else
if(debug) printf(" %s\n",szPath);
FreeLibrary(hRes3);
}
pimage_delay_descriptor++;
}
MSXML2::IXMLDOMNodePtr node,val;
std::string name,arch;
size_t off;
const char *pname;
pname = strrchr(loaded_image->ModuleName,'\\');
if(!pname) pname = strrchr(loaded_image->ModuleName,'/');
if(!pname) pname=loaded_image->ModuleName;
else pname++;
name = pname;
off = name.find_last_of('.');
if(off!=std::string::npos)
name.resize(off);
#ifdef _WIN64
arch="amd64";
#else
arch="x86";
#endif
node = doc->selectSingleNode("/ns:assembly/ns:assemblyIdentity");
if(node==NULL)
{
printf("processing error: no assemblyIdentity\n");
return -1;
}
val = node->attributes->getNamedItem("version");
if(val) val->text=version.c_str();
else
{
val = doc->createAttribute("version");
val->text=version.c_str();
node->attributes->setNamedItem(val);
}
val = node->attributes->getNamedItem("name");
if(val) val->text=name.c_str();
else
{
val = doc->createAttribute("name");
val->text=name.c_str();
node->attributes->setNamedItem(val);
}
val = node->attributes->getNamedItem("processorArchitecture");
if(val) val->text=arch.c_str();
else
{
val = doc->createAttribute("processorArchitecture");
val->text=arch.c_str();
node->attributes->setNamedItem(val);
}
ImageUnload(loaded_image);
const char *_xsl =
"<xsl:stylesheet version=\"1.0\"\n"
" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n"
"<xsl:output method=\"xml\"/>\n"
"<xsl:param name=\"indent-increment\" select=\"' '\" />\n"
"\n"
"<xsl:template match=\"*\">\n"
" <xsl:param name=\"indent\" select=\"'
'\"/>\n"
"\n"
" <xsl:value-of select=\"$indent\"/>\n"
" <xsl:copy>\n"
" <xsl:copy-of select=\"@*\" />\n"
" <xsl:apply-templates>\n"
" <xsl:with-param name=\"indent\"\n"
" select=\"concat($indent, $indent-increment)\"/>\n"
" </xsl:apply-templates>\n"
" <xsl:value-of select=\"$indent\"/>\n"
" </xsl:copy>\n"
"</xsl:template>\n"
"\n"
"<xsl:template match=\"comment()|processing-instruction()\">\n"
" <xsl:copy />\n"
"</xsl:template>\n"
" \n"
"<!-- WARNING: this is dangerous. Handle with care -->\n"
"<xsl:template match=\"text()[normalize-space(.)='']\"/>\n"
"\n"
"</xsl:stylesheet>\n";
MSXML2::IXMLDOMDocument2Ptr xslDoc;
hr = xslDoc.CreateInstance("Msxml2.DOMDocument.6.0");
if (!SUCCEEDED(hr))
{
// the most common thing here is "invalid class string"
hr = xslDoc.CreateInstance("Msxml2.DOMDocument.5.0");
if (!SUCCEEDED(hr))
{
hr = xslDoc.CreateInstance("Msxml2.DOMDocument.4.0");
if (!SUCCEEDED(hr))
{
if(debug) printf("Cannot find MSXML 4.0, 5.0 or 6.0 installed\n");
return -1;
}
else
if(debug) printf("Using MSXML 4.0\n");
}
else
if(debug) printf("Using MSXML 5.0\n");
}
else
if(debug) printf("Using MSXML 6.0\n");
xslDoc->loadXML(_xsl);
_bstr_t txt = doc->transformNode(xslDoc);
DWORD txt_length_in_bytes;
txt_length_in_bytes=txt.length()*2;
if(debug)
{
printf("\n");
printf("text is %d characters long (%d bytes)\n",(int)txt.length(),(int)txt_length_in_bytes);
printf("%s\n",(const char *)txt);
}
GetModuleFileName(hRes,szPath,MAX_PATH);
FreeLibrary(hRes);
HANDLE hUpdate = BeginUpdateResource(szPath,FALSE);
if(!hUpdate)
{
printf("BeginUpdateResource failed!!!\n");
return -1;
}
if (debug||asciimanifest||unicodemanifest)
{
DWORD written=0;
HANDLE hFile;
char manifest[4096], *lastdot;
if (unicodemanifest || debug)
{
strcpy(manifest,szPath);
if ((lastdot=strrchr(manifest,'.'))!=NULL)
strcpy(lastdot,".manifest");
else
strcat(manifest,".manifest");
hFile=CreateFile(manifest,GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_DELETE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile!=INVALID_HANDLE_VALUE)
{
char szBOM[] = "\377\376\0"; // 0xFF, 0xFE // leave off TEXT() macro.
/* file begins with FF FE or FE FF (Reversed Byte Order Mark) */
// this will write a UNICODE file:
WriteFile(hFile,(LPVOID)szBOM,2,&written,NULL);
WriteFile(hFile,(LPVOID)(const wchar_t *)txt,txt_length_in_bytes,&written,NULL);
CloseHandle(hFile);
if (debug) printf("Unicode manifest successfully written to %s!\n",manifest);
}
}
if (asciimanifest || debug)
{
strcpy(manifest,szPath);
if ((lastdot=strrchr(manifest,'.'))!=NULL)
strcpy(lastdot,"-txt.manifest");
else
strcat(manifest,"-txt.manifest");
hFile=CreateFile(manifest,GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_DELETE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile!=INVALID_HANDLE_VALUE)
{
WriteFile(hFile,(LPVOID)(const char *)txt,txt.length(),&written,NULL);
CloseHandle(hFile);
if (debug) printf("ASCII manifest successfully written to %s!\n",manifest);
}
}
}
if(!UpdateResource(hUpdate,RT_MANIFEST,MAKEINTRESOURCE(1),g_wManifestLanguage,(LPVOID)(const char *)txt,txt.length()))
{
printf("UpdateResource failed!!\n");
return -1;
}
else
if(debug) printf("UpdateResource succeeded!\n");
if(!EndUpdateResource(hUpdate, FALSE))
{
printf("EndUpdateResource failed!!\n");
return -1;
}
else
if(debug) printf("EndUpdateResource succeeded!\n");
hRes = LoadLibraryEx(argv[1],NULL,DONT_RESOLVE_DLL_REFERENCES);
if (hRes==NULL)
return -1;
if (!donotstop)
{
if(debug) printf("Press a key to exit\n");
getchar();
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1