|
|
// ===========================================================================
// File: HOOKS.CXX
// implements CSetupHook
//
#include <cdlpch.h>
#include "advpkp.h"
#include "advpub.h"
CRunSetupHook g_RunSetupHook; extern DWORD g_dwCodeDownloadSetupFlags;
// ---------------------------------------------------------------------------
// %%Function: CSetupHook::CSetupHook
// ---------------------------------------------------------------------------
CSetupHook::CSetupHook( CDownload *pdl, LPCSTR szHook, LPCSTR szInf, LPCSTR szInfSection, DWORD flags, HRESULT *phr) : m_pdl(pdl), m_flags(flags), m_state(INSTALL_INIT) { DEBUG_ENTER((DBG_DOWNLOAD, None, "CSetupHook::CSetupHook", "this=%#x, %.80q, %.80q, %.80q, %#x, %#x", this, pdl, szHook, szInf, szInfSection, flags, phr )); Assert(szInf);
*phr = S_OK;
if (szInf) {
m_szInf= new char [lstrlen(szInf)+1];
if (m_szInf) lstrcpy(m_szInf, szInf); else *phr = E_OUTOFMEMORY; } else { m_szInf = NULL; }
if (szInfSection) {
m_szInfSection = new char [lstrlen(szInfSection)+1];
if (m_szInfSection) lstrcpy(m_szInfSection, szInfSection); else *phr = E_OUTOFMEMORY; } else { m_szInfSection = NULL; }
if (szHook) {
m_szHook = new char [lstrlen(szHook)+1];
if (m_szHook) lstrcpy(m_szHook, szHook); else *phr = E_OUTOFMEMORY; } else { m_szHook = NULL; }
DEBUG_LEAVE(0); } // CSetupHook
// ---------------------------------------------------------------------------
// %%Function: CSetupHook::~CSetupHook
// ---------------------------------------------------------------------------
CSetupHook::~CSetupHook() { DEBUG_ENTER((DBG_DOWNLOAD, None, "CSetupHook::~CSetupHook", "this=%#x", this )); if (m_szInf) SAFEDELETE(m_szInf);
if (m_szInfSection) SAFEDELETE(m_szInfSection);
if (m_szHook) SAFEDELETE(m_szHook);
DEBUG_LEAVE(0); } // ~CSetupHook
// ---------------------------------------------------------------------------
// %%Function: CSetupHook::ExpandVar
// ---------------------------------------------------------------------------
HRESULT CSetupHook::ExpandVar( LPSTR& pchSrc, // passed by ref!
LPSTR& pchOut, // passed by ref!
DWORD& cbLen, // passed by ref!
DWORD cbBuffer, const char * szVars[], const char * szValues[]) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CSetupHook::ExpandVar", "%#x, %#x, %#x, %#x, %#x, %#x", &pchSrc, &pchOut, &cbLen, cbBuffer, szVars, szValues )); HRESULT hr = S_FALSE; int cbvar = 0;
Assert (*pchSrc == '%');
for (int i=0; szVars[i] && (cbvar = lstrlen(szVars[i])) ; i++) { // for each variable
int cbneed = 0;
if ( (szValues[i] == NULL) || !(cbneed = lstrlen(szValues[i]))) continue;
cbneed++; // add for nul
if (0 == strncmp(szVars[i], pchSrc, cbvar)) {
// found something we can expand
if ((cbLen + cbneed) >= cbBuffer) { // out of buffer space
*pchOut = '\0'; // term
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); goto Exit; }
lstrcpy(pchOut, szValues[i]); cbLen += (cbneed -1); //don't count the nul
pchSrc += cbvar; // skip past the var in pchSrc
pchOut += (cbneed -1); // skip past dir in pchOut
hr = S_OK; goto Exit;
} }
Exit:
DEBUG_LEAVE(hr); return hr; }
// ---------------------------------------------------------------------------
// %%Function: CSetupHook::TranslateString
// ---------------------------------------------------------------------------
HRESULT CSetupHook::TranslateString() { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CSetupHook::TranslateString", "this=%#x", this )); Assert(m_pdl); Assert(m_szInf); Assert(m_szHook);
HRESULT hr = S_OK;
DWORD_PTR flags = (g_dwCodeDownloadSetupFlags & CDSF_USE_SETUPAPI)?RSC_FLAG_SETUPAPI:0;
// there's a command line in the run= command.
// have advpack tranalate it for us.
DWORD dwBufferSize = 0; DWORD dwRequiredSize = 0;
// get reqd size to hold expanded string
#ifdef WX86
if (m_pdl->GetCodeDownload()->GetMultiArch()->GetRequiredArch() == PROCESSOR_ARCHITECTURE_INTEL) { hr = g_RunSetupHook.TranslateInfStringX86( m_pdl->GetCodeDownload()->GetMainInf(), // inf name
NULL, // use DefaultInstall
m_szHook, // hook section name
"run", // key name
NULL, // find out size reqd.
dwBufferSize, &dwRequiredSize, (PVOID)flags); } else { hr = g_RunSetupHook.TranslateInfString( m_pdl->GetCodeDownload()->GetMainInf(), // inf name
NULL, // use DefaultInstall
m_szHook, // hook section name
"run", // key name
NULL, // find out size reqd.
dwBufferSize, &dwRequiredSize, (PVOID)flags); } #else
hr = g_RunSetupHook.TranslateInfString( m_pdl->GetCodeDownload()->GetMainInf(), // inf name
NULL, // use DefaultInstall
m_szHook, // hook section name
"run", // key name
NULL, // find out size reqd.
dwBufferSize, &dwRequiredSize, (PVOID)flags); #endif
if (FAILED(hr)) goto Exit;
Assert(dwRequiredSize);
if (m_szInf) SAFEDELETE(m_szInf);
m_szInf= new char [(dwBufferSize = dwRequiredSize+1)];
if (!m_szInf) { hr = E_OUTOFMEMORY; goto Exit; }
// the real thing
#ifdef WX86
if (m_pdl->GetCodeDownload()->GetMultiArch()->GetRequiredArch() == PROCESSOR_ARCHITECTURE_INTEL) { hr = g_RunSetupHook.TranslateInfStringX86( m_pdl->GetCodeDownload()->GetMainInf(), // inf name
NULL, // use DefaultInstall
m_szHook, // hook section name
"run", // key name
m_szInf, dwBufferSize, &dwRequiredSize, (PVOID)flags); } else { hr = g_RunSetupHook.TranslateInfString( m_pdl->GetCodeDownload()->GetMainInf(), // inf name
NULL, // use DefaultInstall
m_szHook, // hook section name
"run", // key name
m_szInf, dwBufferSize, &dwRequiredSize, (PVOID)flags); } #else
hr = g_RunSetupHook.TranslateInfString( m_pdl->GetCodeDownload()->GetMainInf(), // inf name
NULL, // use DefaultInstall
m_szHook, // hook section name
"run", // key name
m_szInf, dwBufferSize, &dwRequiredSize, (PVOID)flags); #endif
Exit:
DEBUG_LEAVE(hr); return hr; }
// ---------------------------------------------------------------------------
// %%Function: CSetupHook::ExpandCommandLine
// ---------------------------------------------------------------------------
HRESULT CSetupHook::ExpandCommandLine( LPSTR szSrc, LPSTR szBuf, DWORD cbBuffer, const char * szVars[], const char * szValues[]) { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CSetupHook::ExpandCommandLine", "%.80q, %.80q, %#x, %#x, %#x", szSrc, szBuf, cbBuffer, szVars, szValues )); Assert(cbBuffer);
HRESULT hr = S_FALSE;
LPSTR pchSrc = szSrc; // start parsing at begining of cmdline
LPSTR pchOut = szBuf; // set at begin of out buffer
DWORD cbLen = 0;
while (*pchSrc) {
// look for match of any of our env vars
if (*pchSrc == '%') {
HRESULT hr1 = ExpandVar(pchSrc, pchOut, cbLen, // all passed by ref!
cbBuffer, szVars, szValues);
if (FAILED(hr1)) { hr = hr1; goto Exit; }
if (hr1 == S_OK) { // expand var expanded this
hr = hr1; continue; } } // copy till the next % or nul
if ((cbLen + 1) < cbBuffer) {
*pchOut++ = *pchSrc++; cbLen++;
} else {
// out of buffer space
*pchOut = '\0'; // term
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); goto Exit;
}
}
*pchOut = '\0'; // term
Exit:
DEBUG_LEAVE(hr); return hr; }
// ---------------------------------------------------------------------------
// %%Function: CSetupHook::Run
// ---------------------------------------------------------------------------
HRESULT CSetupHook::Run() { DEBUG_ENTER((DBG_DOWNLOAD, Hresult, "CSetupHook::Run", "this=%#x", this )); Assert(m_pdl); CCodeDownload *pcdl = m_pdl->GetCodeDownload(); Assert(pcdl); HWND hWnd = pcdl->GetClientBinding()->GetHWND();
HANDLE hExe = INVALID_HANDLE_VALUE; HRESULT hr = S_OK; DWORD flags = m_flags;
#define SIZE_CMD_LINE 2048
char szBuf[SIZE_CMD_LINE]; // enough for commandline
DWORD nStatusText = 0; WCHAR szStatusText[SIZE_CMD_LINE];
Assert(m_szInf);
// BEGIN NOTE: add vars and values in matching order
// add a var by adding a new define VAR_NEW_VAR = NUM_VARS++
const char *szVars[] = {
#define VAR_EXTRACT_DIR 0 // dir hook CABs are expanded to temporarily
"%EXTRACT_DIR%",
#define VAR_OBJECT_DIR 1 // dir the main object will be installed to
"%OBJECT_DIR%", // usually activex cache dir, sometimes
// a conflict dir or dir of prev version
// of object
#define VAR_SRC_URL 2 // CODEBASE where we got this from
"%SRC_URL%",
#define NUM_VARS 3
"" };
char szSrcURL[INTERNET_MAX_URL_LENGTH]; LPCWSTR wzSrcURL = NULL;
szSrcURL[0] = '\0'; if ((wzSrcURL = GetSrcURL()) != NULL) { WideCharToMultiByte(CP_ACP, 0, wzSrcURL, -1, szSrcURL, MAX_PATH, 0, 0); }
const char *szValues[NUM_VARS + 1]; szValues[VAR_EXTRACT_DIR] = GetHookDir(); szValues[VAR_OBJECT_DIR] = GetObjectDir(); szValues[VAR_SRC_URL] = szSrcURL; szValues[NUM_VARS] = NULL; // END NOTE: add vars and values in matching order
if (m_flags & RSC_FLAG_INF) {
flags |= RSC_FLAG_QUIET;
if (g_dwCodeDownloadSetupFlags & CDSF_USE_SETUPAPI) flags |= RSC_FLAG_SETUPAPI;
// get fully qualified name for INF
if (GetHookDir()) {
if (!catDirAndFile(szBuf, SIZE_CMD_LINE, GetHookDir(), m_szInf)) { hr = E_UNEXPECTED; goto Exit; } } else {
// no hook dir
Assert(m_pdl->GetExtn() != FILEXTN_CAB);
StrNCpy(szBuf, m_pdl->GetFileName(), sizeof(szBuf)); }
} else {
// cmd line
// have ADVPACK expand out custom LDID vars in run= cmdline
// then we will process for our own vars
// this allows the user to specify custom dirs thru the INF
// and use it in the cmd line off registry keys
hr = TranslateString(); if (FAILED(hr)) goto Exit;
// look for and substitute variables like %EXTRACT_DIR%
// and expand out the command line
hr = ExpandCommandLine(m_szInf, szBuf, SIZE_CMD_LINE, szVars, szValues);
if (FAILED(hr)) goto Exit;
hr = S_OK; // reset
}
nStatusText = MultiByteToWideChar(CP_ACP, 0, szBuf, -1, szStatusText, SIZE_CMD_LINE);
#ifdef WX86
if (m_pdl->GetCodeDownload()->GetMultiArch()->GetRequiredArch() == PROCESSOR_ARCHITECTURE_INTEL) { hr = g_RunSetupHook.RunSetupCommandX86(hWnd, szBuf, m_szInfSection, // extracted files in this dir
(char *)((GetHookDir())?GetHookDir():m_pdl->GetCodeDownload()->GetCacheDir()), NULL, /*title*/ &hExe, // handle to wait on for EXE
flags, NULL); } else { hr = g_RunSetupHook.RunSetupCommand(hWnd, szBuf, m_szInfSection, // extracted files in this dir
(char *)((GetHookDir())?GetHookDir():m_pdl->GetCodeDownload()->GetCacheDir()), NULL, /*title*/ &hExe, // handle to wait on for EXE
flags, NULL); } #else
hr = g_RunSetupHook.RunSetupCommand(hWnd, szBuf, m_szInfSection, // extracted files in this dir
(char *)((GetHookDir())?GetHookDir():m_pdl->GetCodeDownload()->GetCacheDir()), NULL, /*title*/ &hExe, // handle to wait on for EXE
flags, NULL); #endif
if (SUCCEEDED(hr) && (m_flags & RSC_FLAG_INF)) {
// pass a notification to reboot
if (hr == ERROR_SUCCESS_REBOOT_REQUIRED) {
ICodeInstall* pCodeInstall = pcdl->GetICodeInstall(); if (pCodeInstall) { pCodeInstall->OnCodeInstallProblem( CIP_NEED_REBOOT, NULL, szStatusText, 0); }
pcdl->SetRebootRequired(); hr = S_OK; } }
// if we launched an EXE then we would have to mark as waiting for it
if (hExe != INVALID_HANDLE_VALUE) { pcdl->SetWaitingForEXE(szBuf, FALSE /*don't delete EXE */); pcdl->SetWaitingForEXEHandle(hExe); }
Exit:
if (FAILED(hr)) { pcdl->CodeDownloadDebugOut(DEB_CODEDL, TRUE, ID_CDLDBG_RUNSETUPHOOK_FAILED, hr, m_szInf); } else { pcdl->CodeDownloadDebugOut(DEB_CODEDL, TRUE, ID_CDLDBG_HOOK_COMPLETE, m_szHook);
}
SetState(INSTALL_DONE);
DEBUG_LEAVE(hr); return hr; }
|