514 lines
14 KiB
C++
514 lines
14 KiB
C++
|
// ===========================================================================
|
||
|
// 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)
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
} // CSetupHook
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CSetupHook::~CSetupHook
|
||
|
// ---------------------------------------------------------------------------
|
||
|
CSetupHook::~CSetupHook()
|
||
|
{
|
||
|
if (m_szInf)
|
||
|
SAFEDELETE(m_szInf);
|
||
|
|
||
|
if (m_szInfSection)
|
||
|
SAFEDELETE(m_szInfSection);
|
||
|
|
||
|
if (m_szHook)
|
||
|
SAFEDELETE(m_szHook);
|
||
|
|
||
|
} // ~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[])
|
||
|
{
|
||
|
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:
|
||
|
|
||
|
return hr;
|
||
|
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CSetupHook::TranslateString
|
||
|
// ---------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
CSetupHook::TranslateString()
|
||
|
{
|
||
|
Assert(m_pdl);
|
||
|
Assert(m_szInf);
|
||
|
Assert(m_szHook);
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
DWORD 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:
|
||
|
|
||
|
return hr;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CSetupHook::ExpandCommandLine
|
||
|
// ---------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
CSetupHook::ExpandCommandLine(
|
||
|
LPSTR szSrc,
|
||
|
LPSTR szBuf,
|
||
|
DWORD cbBuffer,
|
||
|
const char * szVars[],
|
||
|
const char * 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:
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CSetupHook::Run
|
||
|
// ---------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
CSetupHook::Run()
|
||
|
{
|
||
|
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);
|
||
|
|
||
|
lstrcpy(szBuf, m_pdl->GetFileName());
|
||
|
}
|
||
|
|
||
|
} 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);
|
||
|
|
||
|
return hr;
|
||
|
}
|