📄 crtsis.cpp
字号:
// CRTSIS.CPP// Copyright (c) 1997-1999 Symbian Ltd. All rights reserved.//// Handles creation of a SIS file//// ===========================================================================// INCLUDES// ===========================================================================#include "utils.h"#include <windows.h>#include <assert.h>#include <tchar.h>#include <wchar.h>#include <time.h>#include <stdio.h>#include "crtsis.h"#include "parsepkg.h"//#ifndef DIGITAL_SIGNATURES//#define DIGITAL_SIGNATURES//#endif#ifdef DIGITAL_SIGNATURES#undef DIGITAL_SIGNATURES#endif#ifdef DIGITAL_SIGNATURES// implies you ''have'' to use wincrypt.lib #include <WinHash.h>#include <WinKey.h>#include <WinSHA1.h>#include <WinDSA.h>#include <WinEncrypt.h>#include <winparsepkcs7.h>#include <winB64Decrypt.h>#endif// ===========================================================================// CONSTANTS// ===========================================================================#define HASHLEN 256#define CIPHERTEXTLEN 2048#define Y2K_FIX 1900// CRC calulation lookup tableconst WORD crcTab[256] = {0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,0x8108,0x9129,0xa14a, 0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294, 0x72f7,0x62d6,0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,0x2462, 0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,0xa56a,0xb54b,0x8528,0x9509, 0xe5ee,0xf5cf,0xc5ac,0xd58d,0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695, 0x46b4,0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,0x48c4,0x58e5, 0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948, 0x9969,0xa90a,0xb92b,0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12, 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,0x6ca6,0x7c87,0x4ce4, 0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b, 0x8d68,0x9d49,0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,0xff9f, 0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,0x9188,0x81a9,0xb1ca,0xa1eb, 0xd10c,0xc12d,0xf14e,0xe16f,0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046, 0x6067,0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,0x02b1,0x1290, 0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e, 0xe54f,0xd52c,0xc50d,0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405, 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,0x26d3,0x36f2,0x0691, 0x16b0,0x6657,0x7676,0x4615,0x5634,0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9, 0xb98a,0xa9ab,0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,0xcb7d, 0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,0x4a75,0x5a54,0x6a37,0x7a16, 0x0af1,0x1ad0,0x2ab3,0x3a92,0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8, 0x8dc9,0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,0xef1f,0xff3e, 0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,0x6e17,0x7e36,0x4e55,0x5e74,0x2e93, 0x3eb2,0x0ed1,0x1ef0 };// ===========================================================================// CSISWriter// Holds SIS file info, as generated by the parser and builds the output SIS file.// All strings are held internally by this class as UNICODE (wide) strings.// ===========================================================================CSISWriter::CSISWriter():m_dwUID(0x00000000),m_wMajor(0),m_wMinor(0),m_dwBuild(0),m_wType(EInstSISApp),m_wFlags(0),m_wNumLangs(0),m_pLangStringBase(NULL),m_pLangBase(NULL),m_pPkgLineBase(NULL),m_pDependBase(NULL),m_pSignatureBase(NULL),m_pCapabilityBase(NULL),m_bCmdPassword(FALSE),m_pObserver(NULL) { ; }void CSISWriter::Release()// Dispose of components resources { // remove any temporary files CleanupTemp(); // free up allocated structures LANGSTRINGNODE *pLangStringNode = m_pLangStringBase; while(m_pLangStringBase) { pLangStringNode = pLangStringNode->pNext; delete m_pLangStringBase; m_pLangStringBase = pLangStringNode; } LANGNODE *pLangNode = m_pLangBase; while(m_pLangBase) { pLangNode = pLangNode->pNext; delete m_pLangBase; m_pLangBase = pLangNode; } PKGLINENODE *pPkgLineNode = m_pPkgLineBase; while(m_pPkgLineBase) { pPkgLineNode = m_pPkgLineBase->pNext; switch (m_pPkgLineBase->iPackageLineType) { case EInstPkgLineFile: case EInstPkgLineLanguageFile: delete m_pPkgLineBase->file; break; case EInstPkgLineOption: LANGSTRINGNODE *pLangStringNode2; pLangStringNode = m_pPkgLineBase->option->pLangStringBase; while(pLangStringNode) { pLangStringNode2 = pLangStringNode->pNext; delete pLangStringNode; pLangStringNode = pLangStringNode2; } delete m_pPkgLineBase->option; break; case EInstPkgLineCondIf: case EInstPkgLineCondElseIf: ReleaseCondExpr(m_pPkgLineBase->cond); break; case EInstPkgLineCondElse: case EInstPkgLineCondEndIf: break; } delete m_pPkgLineBase; m_pPkgLineBase = pPkgLineNode; } DEPENDNODE *pDependNode = m_pDependBase; while(m_pDependBase) { pDependNode = pDependNode->pNext; pLangStringNode = m_pDependBase->pLangStringBase; while(m_pLangStringBase) { pLangStringNode = pLangStringNode->pNext; delete m_pLangStringBase; m_pLangStringBase = pLangStringNode; } delete m_pDependBase; m_pDependBase = pDependNode; } if (m_pSignatureBase) delete m_pSignatureBase; CAPABILITYNODE *pCapabilityNode = m_pCapabilityBase; while(m_pCapabilityBase) { pCapabilityNode = pCapabilityNode->pNext; delete m_pCapabilityBase; m_pCapabilityBase = pCapabilityNode; } }void CSISWriter::ReleaseCondExpr(PKGLINECONDITION* expr)// recursively called to free up condition expression { if (expr) { switch (expr->exprType) { case EInstCondBinOpEq: case EInstCondBinOpNe: case EInstCondBinOpGt: case EInstCondBinOpLt: case EInstCondBinOpGe: case EInstCondBinOpLe: case EInstCondLogOpAnd: case EInstCondLogOpOr: ReleaseCondExpr(expr->b.pLhs); ReleaseCondExpr(expr->b.pRhs); break; case EInstCondUnaryOpNot: ReleaseCondExpr(expr->pExpr); break; case EInstCondFuncAppCap: ReleaseCondExpr(expr->pArg[0]); ReleaseCondExpr(expr->pArg[1]); break; case EInstCondFuncExists: case EInstCondFuncDevCap: ReleaseCondExpr(expr->pArg[0]); break; case EInstCondPrimTypeString: case EInstCondPrimTypeVariable: case EInstCondPrimTypeNumber: delete expr->pPrim; break; default: break; } delete expr; } }void CSISWriter::SetCmdPassword(LPCWSTR pszCmdPassword) { wcscpy(m_pszCmdPassword, pszCmdPassword); m_bCmdPassword = TRUE; }BOOL CSISWriter::GetCmdPassword(LPWSTR pszCmdPassword) const { wcscpy(pszCmdPassword, m_pszCmdPassword); return m_bCmdPassword; }void CSISWriter::WriteSIS(LPCWSTR pszTargetFile, BOOL fIsStub /*=FALSE*/)// Construct the output SIS file// Inputs : hFile The file handle to write to// fIsStub IS this a stub SIS file (stub SIS files have no CODE block) { if(m_wFlags & EInstIsUnicode) { CSISFileGeneratorT<unsigned short> gen(this); gen.GenerateSISFile(pszTargetFile, fIsStub); } else { CSISFileGeneratorT<char> gen(this); gen.GenerateSISFile(pszTargetFile, fIsStub); } }void CSISWriter::AddLanguageNode(LANGNODE *pLNode)// Adds a language node// Inputs : pLNode The node to add { pLNode->pNext = m_pLangBase; m_pLangBase = pLNode; m_wNumLangs++; }void CSISWriter::AddLangStringNode(LANGSTRINGNODE *pLSNode)// Adds a language string node// Inputs : pLSNode The node to add { pLSNode->pNext = m_pLangStringBase; m_pLangStringBase = pLSNode; }void CSISWriter::AddPkgLineNode(PKGLINENODE *pNode)// Adds a PKG line node// Inputs : pNode The node to add { pNode->pNext = m_pPkgLineBase; m_pPkgLineBase = pNode; }void CSISWriter::AddDependencyNode(DEPENDNODE *pNode)// Does exactly what it says on the tin!// Inputs : pNode The node to add { pNode->pNext = m_pDependBase; m_pDependBase = pNode; }void CSISWriter::AddSignatureNode(SIGNATURENODE *pSig)// Sets the digital signature// Inputs : pSig The node to add { m_pSignatureBase = pSig; }void CSISWriter::AddCapabilityNode(CAPABILITYNODE *pNode)// Does exactly what it says on the tin!// Inputs : pNode The node to add { pNode->pNext = m_pCapabilityBase; m_pCapabilityBase = pNode; }BOOL CSISWriter::AreLangStringInit()// Is there a language string node defined? (i.e. has the pkg language header line been parsed?) { return (m_pLangStringBase!=NULL); }void CSISWriter::SetVersionInfo(DWORD dwUID, WORD wMajor, WORD wMinor, DWORD dwBuild, TSISType wType, WORD wFlags)// Inputs : dwUID Installee app's uid// dwMajor, dwMinor, dwBuild The version numbers// wType SIS file type// wFlags Installation flags { m_dwUID = dwUID; m_wMajor = wMajor; m_wMinor = wMinor; m_dwBuild = dwBuild; m_wType = wType; m_wFlags = wFlags; }void CSISWriter::QueryVersionInfo (WORD *wMajor, WORD *wMinor, DWORD *dwBuild) const// Inputs : dwMajor, dwMinor, dwBuild The destinations for the version numbers { *wMajor = m_wMajor; *wMinor = m_wMinor; *dwBuild = m_dwBuild; }void CSISWriter::SetLangDependFileDestinations(LPCWSTR pszDest, LPCWSTR pszMimeType, DWORD dwType, DWORD dwOptions)// Purpose : Patches the last 'numlang' files with a target path and flags (including the// OPTFILE_LANGUAGEDEPENDENT flag)// Inputs : pszDest The target path// : pszMimeType The mime type (if relevant)// dwOptions Any specified flags { PKGLINENODE *pNode = m_pPkgLineBase; WORD wNumLangs = 0; while(pNode && (wNumLangs++ < m_wNumLangs)) { wcscpy(pNode->file->pszDest, pszDest); pNode->iPackageLineType = EInstPkgLineLanguageFile; pNode->file->type = (TInstFileType)dwType; switch (pNode->file->type) { case EInstFileTypeText: pNode->file->options.iTextOption=(TInstFileTextOption)dwOptions; break; case EInstFileTypeRun: pNode->file->options.iRunOption=(TInstFileRunOption)dwOptions; break; case EInstFileTypeMime: pNode->file->options.iMimeOption=(TInstFileMimeOption)dwOptions; wcscpy(pNode->file->pszMimeType, pszMimeType); break; default: break; } pNode = pNode->pNext; } }void CSISWriter::SetLangDependCompDestinations(DWORD dwUID)// Purpose : Sets the component id of the last 'numlang' file nodes, and sets their flags to// OPTFILE_LANGUAGEDEPENDENT | OPTFILE_COMPONENT;// Inputs : dwUID The components UID { PKGLINENODE *pNode = m_pPkgLineBase; WORD wNumLangs = 0; while(pNode && (wNumLangs++ < m_wNumLangs)) { pNode->iPackageLineType = EInstPkgLineLanguageFile; pNode->file->type = EInstFileTypeComponent; pNode->file->options.iComponentUid = dwUID; pNode = pNode->pNext; } }// ===========================================================================// CSISFileGeneratorBase// Handles most of the SIS file generation operation. Defers the charater// width specific stuff to a derived template class...// ===========================================================================CSISFileGeneratorBase::CSISFileGeneratorBase(const CSISWriter *pSISWriter):m_pSISWriter(pSISWriter) { ; }CSISFileGeneratorBase::~CSISFileGeneratorBase() { ; }void CSISFileGeneratorBase::GenerateSISFile(LPCWSTR pszTargetFile, BOOL fIsStub /* = FALSE */)// Purpose : Construct// Inputs : hFile The file handle to write to// fIsStub IS this a stub SIS file (stub SIS files have no CODE block)// Returns : Success or failure (actually TRUE or throws an EGeneratorException { m_hFile = ::MakeSISOpenFile(pszTargetFile, GENERIC_WRITE, CREATE_ALWAYS); if(m_hFile == INVALID_HANDLE_VALUE) throw ErrCannotWriteFile; m_stubFile=fIsStub; // convert any text files to unicode if necessary if (SizeOfChar()!=1 && !m_stubFile) CheckUnicodeTextFiles(); // Estimate the maximum amount of space an installation could require EstimateInstallationSizeL(); // Compress files into temp directory CompressFiles(); //Re-Write Certificate files ParseCertificates(); // Calculate the offsets CalculateOffsets(); m_wCheck = 0; // reset checksum WriteHeaderL(); WriteLanguageL(); WritePkgLinesL(); WriteDependL(); WriteCertificatesL(); WriteCapabilitiesL(); WriteStringsL(); if(!m_stubFile) WriteCodeL(); WriteCrcL(); ::CloseHandle(m_hFile); WriteSignatureL(pszTargetFile); }void CSISFileGeneratorBase::CheckUnicodeTextFiles()// Converts any text files to UNICODE { Verbage(_T("Converting text files to unicode")); PKGLINENODE *pNode = (PKGLINENODE *)m_pSISWriter->GetPkgLineBase(); BOOL converted=FALSE; while(pNode) { if (pNode->iPackageLineType==EInstPkgLineFile || pNode->iPackageLineType==EInstPkgLineLanguageFile) { WORD wMaxLangs=1; if (pNode->iPackageLineType==EInstPkgLineLanguageFile) wMaxLangs = m_pSISWriter->GetNoLanguages(); WORD wNumLang = 0; while(pNode && (wNumLang < wMaxLangs)) { if(pNode->file->type==EInstFileTypeText) { // have a text file BOOL littleEndian; try { if (!FileIsUnicode(pNode->file->pszSource,littleEndian)) { LPWSTR pszTempSource=ConvertFileToUnicode(pNode->file->pszSource); wcscpy(pNode->file->pszSource, pszTempSource); converted=TRUE; } else if (!littleEndian) { LPWSTR pszTempSource=ConvertFileToLittleEndianUnicode(pNode->file->pszSource); wcscpy(pNode->file->pszSource, pszTempSource); converted=TRUE; } } catch (TUtilsException excp) {#ifdef _UNICODE m_pSISWriter->GetObserver()->DoErrMsg((const _TCHAR*)pNode->file->pszSource); // @todo#else DWORD length=wcslen(pNode->file->pszSource); LPSTR fName=MakeMBCSString(pNode->file->pszSource, CP_ACP, length); m_pSISWriter->GetObserver()->DoErrMsg((const _TCHAR*)fName); delete [] fName;#endif throw excp; } HANDLE hInFile = ::MakeSISOpenFile(pNode->file->pszSource, GENERIC_READ, OPEN_EXISTING); if(hInFile == INVALID_HANDLE_VALUE) throw ErrCannotOpenFile; if (converted) pNode->file->dwSize=::GetFileSize(hInFile, NULL); ::CloseHandle(hInFile); } pNode = pNode->pNext; wNumLang++; } } else pNode = pNode->pNext; } }void CSISFileGeneratorBase::CalculateOffsets()// Calculates the offsets of the various component blocks from the head of the file { assert(m_pSISWriter); // Calculate the language offset (The size of the HEADER block) ------------------------------- m_dwOffLang = sizeof(TInstInstallation); // Calculate the PKG lines offset (The size of the LANGUAGE block) -------------------------------- m_dwOffPkgLines = m_dwOffLang + (sizeof(TInstLang) * m_pSISWriter->GetNoLanguages()); // Calculate the dependency offset (The size of the PKG lines block) ------------------------------ m_dwOffDepend = m_dwOffPkgLines; DWORD stringSizes=0; const PKGLINENODE *pNode = m_pSISWriter->GetPkgLineBase(); while(pNode) { m_dwOffDepend += sizeof(TInstPackageLineType); switch (pNode->iPackageLineType) { case EInstPkgLineFile: case EInstPkgLineLanguageFile: { WORD wNumLangs = 1; if (pNode->iPackageLineType==EInstPkgLineLanguageFile) wNumLangs = m_pSISWriter->GetNoLanguages(); m_dwOffDepend += sizeof(TInstFile) + ((sizeof(unsigned long) + sizeof(FOFF) + sizeof(unsigned long)) * wNumLangs) + sizeof(TInstString); stringSizes += (wcslen(pNode->file->pszSource) + wcslen(pNode->file->pszDest)) * SizeOfChar() + wcslen(pNode->file->pszMimeType);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -