453 lines
14 KiB
C++
453 lines
14 KiB
C++
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1994 - 1997.
|
|
//
|
|
// File: script.cpp
|
|
//
|
|
// Contents: Functions for working with Darwin files, both packages,
|
|
// transforms and scripts.
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions: BuildScriptAndGetActInfo
|
|
//
|
|
// History: 1-14-1998 stevebl Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "precomp.hxx"
|
|
|
|
#define REG_TEMP L"temporary key created by ADE"
|
|
|
|
HRESULT GetShellExtensions(HKEY hkey, PACKAGEDETAIL &pd);
|
|
|
|
HRESULT GetCLSIDs(HKEY hkey, PACKAGEDETAIL &pd);
|
|
|
|
HRESULT GetIIDs(HKEY hkey, PACKAGEDETAIL &pd);
|
|
|
|
HRESULT GetTLBs(HKEY hkey, PACKAGEDETAIL &pd);
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: RegDeleteTree
|
|
//
|
|
// Synopsis: deletes a registry key and all of its children
|
|
//
|
|
// Arguments: [hKey] - handle to the key's parent
|
|
// [szSubKey] - name of the key to be deleted
|
|
//
|
|
// Returns: ERROR_SUCCESS
|
|
//
|
|
// History: 1-14-1998 stevebl Moved from old project
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
LONG RegDeleteTree(HKEY hKey, TCHAR * szSubKey)
|
|
{
|
|
HKEY hKeyNew;
|
|
LONG lResult = RegOpenKey(hKey, szSubKey, &hKeyNew);
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
return lResult;
|
|
}
|
|
TCHAR szName[256];
|
|
while (ERROR_SUCCESS == RegEnumKey(hKeyNew, 0, szName, 256))
|
|
{
|
|
RegDeleteTree(hKeyNew, szName);
|
|
}
|
|
RegCloseKey(hKeyNew);
|
|
return RegDeleteKey(hKey, szSubKey);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: BuildScriptAndGetActInfo
|
|
//
|
|
// Synopsis: Builds the script file and fills in the ACTINFO structure
|
|
// member in the PACKAGEDETAIL structure.
|
|
//
|
|
// Arguments: [szScriptRoot] - [in] the subdirectory that the script file
|
|
// should be place in.
|
|
// [pd] - [in/out] package detail structure - see
|
|
// notes for complete list of fields that
|
|
// should be filled in and the list of fields
|
|
// that are set on return
|
|
//
|
|
// Returns: S_OK - success
|
|
// <other> - error
|
|
//
|
|
// Modifies: all fields under pd.pActInfo (only on success)
|
|
// also modifies pd.pInstallInfo->cScriptLen
|
|
//
|
|
// History: 1-14-1998 stevebl Created
|
|
//
|
|
// Notes: On input:
|
|
// pd.cSources must be >= 1.
|
|
// pd.pszSourceList[] contains the MSI package and the list of
|
|
// (if any) transforms to be applied.
|
|
// pd.pPlatformInfo should be completely filled in (only one
|
|
// locale).
|
|
// pd.pInstallInfo->pszScriptFile contains the name of the
|
|
// script file to be generated.
|
|
//
|
|
// On output:
|
|
// The script file will be generated under the appropriate name
|
|
// and in the appropriate directory.
|
|
// pd.pActInfo will be completely filled in.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT BuildScriptAndGetActInfo(CString szScriptRoot, PACKAGEDETAIL & pd)
|
|
{
|
|
CHourglass hourglass;
|
|
HRESULT hr;
|
|
UINT uMsiStatus;
|
|
LONG error;
|
|
int i;
|
|
CString szScriptPath = szScriptRoot;
|
|
szScriptPath += L"\\";
|
|
szScriptPath += pd.pInstallInfo->pszScriptPath;
|
|
CString szTransformList = L"";
|
|
for (i = 1; i < pd.cSources; i++)
|
|
{
|
|
if (i < 1)
|
|
{
|
|
szTransformList += L";";
|
|
}
|
|
szTransformList += pd.pszSourceList[i];
|
|
}
|
|
|
|
// disable MSI ui
|
|
MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
|
|
|
|
// build the script file
|
|
|
|
uMsiStatus = MsiAdvertiseProduct(pd.pszSourceList[0],
|
|
szScriptPath,
|
|
szTransformList,
|
|
LANGIDFROMLCID(pd.pPlatformInfo->prgLocale[0]));
|
|
if (uMsiStatus)
|
|
{
|
|
// an error occured
|
|
return HRESULT_FROM_WIN32((long)uMsiStatus);
|
|
}
|
|
|
|
// get script file length
|
|
HANDLE hFile = CreateFile(szScriptPath,
|
|
GENERIC_READ,
|
|
0,
|
|
0,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0);
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
pd.pInstallInfo->cScriptLen = GetFileSize(hFile, NULL);
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
//
|
|
// dump everyting into the registry
|
|
//
|
|
|
|
// nuke old temporary registry key just to be safe:
|
|
RegDeleteTree(HKEY_CLASSES_ROOT, REG_TEMP);
|
|
|
|
// create temporary registry key
|
|
|
|
DWORD dwDisp;
|
|
HKEY hkey;
|
|
|
|
error = RegCreateKeyEx(HKEY_CLASSES_ROOT,
|
|
REG_TEMP,
|
|
0,
|
|
L"REG_SZ",
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hkey,
|
|
&dwDisp);
|
|
|
|
hr = HRESULT_FROM_WIN32(error);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
uMsiStatus = MsiProcessAdvertiseScript(szScriptPath,
|
|
0,
|
|
hkey,
|
|
FALSE,
|
|
FALSE);
|
|
|
|
hr = HRESULT_FROM_WIN32(uMsiStatus);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// fill in the ActInfo
|
|
GetShellExtensions(hkey, pd);
|
|
GetCLSIDs(hkey, pd);
|
|
GetIIDs(hkey, pd);
|
|
GetTLBs(hkey, pd);
|
|
}
|
|
RegCloseKey(hkey);
|
|
RegDeleteTree(HKEY_CLASSES_ROOT, REG_TEMP);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetShellExtensions
|
|
//
|
|
// Synopsis: fills the shell extension part of the PACKAGEDETAIL structure
|
|
//
|
|
// Arguments: [hkey] - key containing the registry info
|
|
// [pd] - PACKAGEDETAIL structure
|
|
//
|
|
// History: 1-15-1998 stevebl Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT GetShellExtensions(HKEY hkey, PACKAGEDETAIL &pd)
|
|
{
|
|
std::vector<CString> v;
|
|
TCHAR szName[256];
|
|
LONG lResult;
|
|
UINT n = 0;
|
|
while (ERROR_SUCCESS == RegEnumKey(hkey, n++, szName, 256))
|
|
{
|
|
if (szName[0] == L'.')
|
|
{
|
|
v.push_back(szName);
|
|
}
|
|
}
|
|
n = v.size();
|
|
pd.pActInfo->cShellFileExt = n;
|
|
if (n > 0)
|
|
{
|
|
pd.pActInfo->prgShellFileExt = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * n);
|
|
pd.pActInfo->prgPriority = (UINT *) OLEALLOC(sizeof(UINT) * n);
|
|
while (n--)
|
|
{
|
|
CString &sz = v[n];
|
|
sz.MakeLower();
|
|
OLESAFE_COPYSTRING(pd.pActInfo->prgShellFileExt[n], sz);
|
|
pd.pActInfo->prgPriority[n] = 0;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetCLSIDs
|
|
//
|
|
// Synopsis: fills the CLSID part of the PACKAGEDETAIL structure
|
|
//
|
|
// Arguments: [hkey] - key containing the registry info
|
|
// [pd] - PACKAGEDETAIL structure
|
|
//
|
|
// History: 1-15-1998 stevebl Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT GetCLSIDs(HKEY hkey, PACKAGEDETAIL &pd)
|
|
{
|
|
HRESULT hr;
|
|
LONG lResult;
|
|
HKEY hkeyNew;
|
|
lResult = RegOpenKey(hkey, L"CLSID", &hkeyNew);
|
|
if (lResult == ERROR_SUCCESS)
|
|
{
|
|
// Find all the CLSID entries and add them to our vector
|
|
UINT n = 0;
|
|
std::vector<CLASSDETAIL> v;
|
|
TCHAR szName[256];
|
|
while (ERROR_SUCCESS == RegEnumKey(hkeyNew, n++, szName, 256))
|
|
{
|
|
CLASSDETAIL cd;
|
|
memset(&cd, 0, sizeof(CLASSDETAIL));
|
|
hr = CLSIDFromString(szName, &cd.Clsid);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
HKEY hkeyCLSID;
|
|
lResult = RegOpenKey(hkeyNew, szName, &hkeyCLSID);
|
|
if (ERROR_SUCCESS == lResult)
|
|
{
|
|
HKEY hkeySub;
|
|
DWORD dw;
|
|
lResult = RegOpenKey(hkeyCLSID, L"TreatAs", &hkeySub);
|
|
if (ERROR_SUCCESS == lResult)
|
|
{
|
|
dw = 256 * sizeof(TCHAR);
|
|
lResult = RegQueryValueEx(hkeySub, L"", 0, NULL, (LPBYTE) szName, &dw);
|
|
if (ERROR_SUCCESS == lResult)
|
|
{
|
|
CLSIDFromString(szName, &cd.TreatAs);
|
|
}
|
|
RegCloseKey(hkeySub);
|
|
}
|
|
TCHAR szProgID[256];
|
|
szProgID[0] = 0;
|
|
TCHAR szVersionIndependentProgID[256];
|
|
szVersionIndependentProgID[0] = 0;
|
|
lResult = RegOpenKey(hkeyCLSID, L"ProgID", &hkeySub);
|
|
if (ERROR_SUCCESS == lResult)
|
|
{
|
|
dw = 256 * sizeof(TCHAR);
|
|
RegQueryValueEx(hkeySub, L"", 0, NULL, (LPBYTE) szProgID, &dw);
|
|
RegCloseKey(hkeySub);
|
|
}
|
|
lResult = RegOpenKey(hkeyCLSID, L"VersionIndependentProgID", &hkeySub);
|
|
if (ERROR_SUCCESS == lResult)
|
|
{
|
|
dw = 256 * sizeof(TCHAR);
|
|
RegQueryValueEx(hkeySub, L"", 0, NULL, (LPBYTE) szVersionIndependentProgID, &dw);
|
|
RegCloseKey(hkeySub);
|
|
}
|
|
DWORD cProgId = 0;
|
|
if (szProgID[0])
|
|
{
|
|
cProgId++;
|
|
}
|
|
if (szVersionIndependentProgID[0])
|
|
{
|
|
cProgId++;
|
|
}
|
|
if (cProgId > 0)
|
|
{
|
|
cd.cProgId = cProgId;
|
|
cd.prgProgId = (LPOLESTR *) OLEALLOC(sizeof(LPOLESTR) * cProgId);
|
|
cProgId = 0;
|
|
if (szProgID[0])
|
|
{
|
|
OLESAFE_COPYSTRING(cd.prgProgId[cProgId], szProgID);
|
|
cProgId++;
|
|
}
|
|
if (szVersionIndependentProgID[0])
|
|
{
|
|
OLESAFE_COPYSTRING(cd.prgProgId[cProgId], szVersionIndependentProgID);
|
|
}
|
|
}
|
|
RegCloseKey(hkeyCLSID);
|
|
}
|
|
v.push_back(cd);
|
|
}
|
|
}
|
|
RegCloseKey(hkeyNew);
|
|
// create the list of CLASSDETAIL structures
|
|
n = v.size();
|
|
pd.pActInfo->cClasses = n;
|
|
if (n > 0)
|
|
{
|
|
pd.pActInfo->pClasses = (CLASSDETAIL *) OLEALLOC(sizeof(CLASSDETAIL) * n);
|
|
while (n--)
|
|
{
|
|
pd.pActInfo->pClasses[n] = v[n];
|
|
}
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetIIDs
|
|
//
|
|
// Synopsis: fills in the Interface section of the PACKAGEDETAIL structure
|
|
//
|
|
// Arguments: [hkey] - key containing the registry info
|
|
// [pd] - PACKAGEDETAIL structure
|
|
//
|
|
// History: 1-15-1998 stevebl Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT GetIIDs(HKEY hkey, PACKAGEDETAIL &pd)
|
|
{
|
|
HRESULT hr;
|
|
LONG lResult;
|
|
HKEY hkeyNew;
|
|
lResult = RegOpenKey(hkey, L"Interface", &hkeyNew);
|
|
if (lResult == ERROR_SUCCESS)
|
|
{
|
|
// Find all the IID entries and add them to our vector
|
|
UINT n = 0;
|
|
std::vector<GUID> v;
|
|
TCHAR szName[256];
|
|
while (ERROR_SUCCESS == RegEnumKey(hkeyNew, n++, szName, 256))
|
|
{
|
|
GUID g;
|
|
hr = CLSIDFromString(szName, &g);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
v.push_back(g);
|
|
}
|
|
}
|
|
RegCloseKey(hkeyNew);
|
|
// create the list
|
|
n = v.size();
|
|
pd.pActInfo->cInterfaces = n;
|
|
if (n > 0)
|
|
{
|
|
pd.pActInfo->prgInterfaceId = (IID *) OLEALLOC(sizeof(IID) * n);
|
|
while (n--)
|
|
{
|
|
pd.pActInfo->prgInterfaceId[n] = v[n];
|
|
}
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetTLBs
|
|
//
|
|
// Synopsis: fills in the type library section of the PACKAGEDETAIL struct
|
|
//
|
|
// Arguments: [hkey] - key containing the registry info
|
|
// [pd] - PACKAGEDETAIL structure
|
|
//
|
|
// History: 1-15-1998 stevebl Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
HRESULT GetTLBs(HKEY hkey, PACKAGEDETAIL &pd)
|
|
{
|
|
HRESULT hr;
|
|
LONG lResult;
|
|
HKEY hkeyNew;
|
|
lResult = RegOpenKey(hkey, L"TypeLib", &hkeyNew);
|
|
if (lResult == ERROR_SUCCESS)
|
|
{
|
|
// Find all the TLB entries and add them to our vector
|
|
UINT n = 0;
|
|
std::vector<GUID> v;
|
|
TCHAR szName[256];
|
|
while (ERROR_SUCCESS == RegEnumKey(hkeyNew, n++, szName, 256))
|
|
{
|
|
GUID g;
|
|
hr = CLSIDFromString(szName, &g);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
v.push_back(g);
|
|
}
|
|
}
|
|
RegCloseKey(hkeyNew);
|
|
// create the list
|
|
n = v.size();
|
|
pd.pActInfo->cTypeLib = n;
|
|
if (n > 0)
|
|
{
|
|
pd.pActInfo->prgTlbId = (GUID *) OLEALLOC(sizeof(GUID) * n);
|
|
while (n--)
|
|
{
|
|
pd.pActInfo->prgTlbId[n] = v[n];
|
|
}
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|