1465 lines
39 KiB
C++
1465 lines
39 KiB
C++
|
|
|||
|
#include "dsbase.hxx"
|
|||
|
|
|||
|
//
|
|||
|
// List of columns this routine fetches.
|
|||
|
//
|
|||
|
LPOLESTR szInstallInfoColumns =
|
|||
|
L"msiScriptPath,packageFlags,comClassID,packageType,lastUpdateSequence,versionNumberHi,versionNumberLo,localeID,machineArchitecture,oSVersion,fileExtPriority,canUpgradeScript,installUiLevel,executionContext,url,setupCommand";
|
|||
|
|
|||
|
//
|
|||
|
// List of columns this routine fetches.
|
|||
|
//
|
|||
|
LPOLESTR szPackageInfoColumns =
|
|||
|
L"packageName,packageFlags,packageType,msiScriptPath,msiScriptSize,lastUpdateSequence,versionNumberHi,versionNumberLo,localeID,machineArchitecture,oSVersion,canUpgradeScript";
|
|||
|
|
|||
|
//
|
|||
|
// MatchLocale : Compares the packages locale to the client locale.
|
|||
|
// Prescribed order is :
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
BOOL MatchLocale(DWORD dwReqLocale, DWORD dwPkgLocale)
|
|||
|
{
|
|||
|
return ((dwReqLocale == dwPkgLocale) || // locale is matching
|
|||
|
(dwPkgLocale == GetUserDefaultLCID()) || // pkg locale is user default
|
|||
|
(dwPkgLocale == GetSystemDefaultLCID()) || // pkg locale is system default
|
|||
|
(dwPkgLocale == LOCALE_NEUTRAL) // pkg is locale neutral
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
BOOL MatchPlatform(CSPLATFORM *pReqPlatform, CSPLATFORM *pPkgPlatform)
|
|||
|
{
|
|||
|
//
|
|||
|
// ProcessorArch must match
|
|||
|
// AND OS must match
|
|||
|
// AND the OS version reqd by the package MUST be less or equal
|
|||
|
// to the client's OS version
|
|||
|
//
|
|||
|
|
|||
|
return (
|
|||
|
(pReqPlatform->dwPlatformId == pPkgPlatform->dwPlatformId) &&
|
|||
|
(pReqPlatform->dwProcessorArch == pPkgPlatform->dwProcessorArch) &&
|
|||
|
((pReqPlatform->dwVersionHi < pPkgPlatform->dwVersionHi) ||
|
|||
|
((pReqPlatform->dwVersionHi == pPkgPlatform->dwVersionHi) &&
|
|||
|
(pReqPlatform->dwVersionLo <= pPkgPlatform->dwVersionLo))
|
|||
|
)
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
//---------------------------------------------------------------
|
|||
|
// Query
|
|||
|
//----------------------------------------------------------------
|
|||
|
HRESULT
|
|||
|
StartQuery(IDBCreateCommand ** ppIDBCreateCommand)
|
|||
|
{
|
|||
|
|
|||
|
HRESULT hr;
|
|||
|
IDBCreateSession * pIDBCS = NULL;
|
|||
|
IDBInitialize * pIDBInit = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Instantiate a data source object for LDAP provider
|
|||
|
//
|
|||
|
hr = CoCreateInstance(
|
|||
|
CLSID_ADsDSOObject,
|
|||
|
0,
|
|||
|
CLSCTX_INPROC_SERVER,
|
|||
|
IID_IDBInitialize,
|
|||
|
(void **)&pIDBInit
|
|||
|
);
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("CoCreateInstance failed \n");
|
|||
|
goto error;
|
|||
|
}
|
|||
|
|
|||
|
hr = pIDBInit->Initialize();
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("IDBIntialize::Initialize failed \n");
|
|||
|
goto error;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Request the IDBCreateSession interface
|
|||
|
//
|
|||
|
pIDBInit->QueryInterface(
|
|||
|
IID_IDBCreateSession,
|
|||
|
(void**) &pIDBCS);
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("QueryInterface for IDBCreateSession failed \n");
|
|||
|
goto error;
|
|||
|
}
|
|||
|
|
|||
|
pIDBInit->Release();
|
|||
|
pIDBInit = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Create a session returning a pointer to its CreateCommand interface
|
|||
|
//
|
|||
|
hr = pIDBCS->CreateSession(
|
|||
|
NULL,
|
|||
|
IID_IDBCreateCommand,
|
|||
|
(LPUNKNOWN*) ppIDBCreateCommand
|
|||
|
);
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("IDBCreateSession::CreateSession failed \n");
|
|||
|
goto error;
|
|||
|
}
|
|||
|
|
|||
|
pIDBCS->Release();
|
|||
|
pIDBCS = NULL;
|
|||
|
|
|||
|
return S_OK;
|
|||
|
|
|||
|
error:
|
|||
|
|
|||
|
if(pIDBInit)
|
|||
|
pIDBInit->Release();
|
|||
|
if(pIDBCS)
|
|||
|
pIDBCS->Release();
|
|||
|
return -1;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
HRESULT
|
|||
|
EndQuery(IDBCreateCommand * pIDBCreateCommand)
|
|||
|
{
|
|||
|
pIDBCreateCommand->Release();
|
|||
|
return S_OK;
|
|||
|
}
|
|||
|
|
|||
|
HRESULT
|
|||
|
CreateBindingHelper(
|
|||
|
IRowset *pIRowset,
|
|||
|
ULONG cColumns,
|
|||
|
DBBINDING **pprgBindings
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
// ExecuteQuery
|
|||
|
// --------------
|
|||
|
//
|
|||
|
// This is a generic routine.
|
|||
|
// It hides a lot of nuisances with regards to setting up a OLEDB
|
|||
|
// query session, specifying a query command and executing it,
|
|||
|
// associating a provided binding with it and getting an
|
|||
|
// Accessor and Rowset out of all these.
|
|||
|
//
|
|||
|
// The inputs are
|
|||
|
// A IDBCreateCommand object to provide for reuse
|
|||
|
// The Query Command Text
|
|||
|
// Number of Columns in the query
|
|||
|
// Binding Association for Data Access
|
|||
|
// The Returned Set is:
|
|||
|
// Rowset Object
|
|||
|
// Accessor Object
|
|||
|
// Accessor Handle
|
|||
|
|
|||
|
|
|||
|
HRESULT ExecuteQuery (IDBCreateCommand * pIDBCreateCommand,
|
|||
|
LPWSTR pszCommandText,
|
|||
|
UINT nColumns,
|
|||
|
DBBINDING * pBinding,
|
|||
|
HACCESSOR * phAccessor,
|
|||
|
IAccessor ** ppIAccessor,
|
|||
|
IRowset ** ppIRowset
|
|||
|
)
|
|||
|
{
|
|||
|
HRESULT hr;
|
|||
|
ICommand * pICommand = NULL;
|
|||
|
ICommandText * pICommandText = NULL;
|
|||
|
IAccessor * pAccessor = NULL;
|
|||
|
DBBINDING * prgBindings = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Create a command from the session object
|
|||
|
//
|
|||
|
|
|||
|
hr = pIDBCreateCommand->CreateCommand(
|
|||
|
NULL,
|
|||
|
IID_ICommandText,
|
|||
|
(LPUNKNOWN*) &pICommandText);
|
|||
|
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf(" IDBCreateCommand::CreateCommand failed, hr = 0x%x\n", hr);
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
hr = pICommandText->SetCommandText(
|
|||
|
DBGUID_LDAPDialect,
|
|||
|
pszCommandText
|
|||
|
);
|
|||
|
|
|||
|
CSDbgPrint(("CS: Query: %S\n", pszCommandText));
|
|||
|
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("ICommandText::CommandText failed \n");
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
hr = pICommandText->QueryInterface(
|
|||
|
IID_ICommand,
|
|||
|
(void**) &pICommand);
|
|||
|
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("QueryInterface for ICommand failed \n");
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
hr = pICommandText->Release();
|
|||
|
|
|||
|
//
|
|||
|
// Do the search and get back a rowset
|
|||
|
//
|
|||
|
hr = pICommand->Execute(
|
|||
|
NULL,
|
|||
|
IID_IRowset,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
(LPUNKNOWN *)ppIRowset);
|
|||
|
|
|||
|
if (FAILED(hr))
|
|||
|
{
|
|||
|
printf("ICommand::Execute failed \n");
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
pICommand->Release();
|
|||
|
|
|||
|
|
|||
|
hr= (*ppIRowset)->QueryInterface(
|
|||
|
IID_IAccessor,
|
|||
|
(void**) ppIAccessor);
|
|||
|
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("QueryInterface for IAccessor failed \n");
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// With the bindings create the accessor
|
|||
|
//
|
|||
|
if (!pBinding)
|
|||
|
{
|
|||
|
//
|
|||
|
// Create a binding from data type
|
|||
|
//
|
|||
|
hr = CreateBindingHelper(
|
|||
|
*ppIRowset,
|
|||
|
nColumns,
|
|||
|
&prgBindings);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
hr = (*ppIAccessor)->CreateAccessor(
|
|||
|
DBACCESSOR_ROWDATA,
|
|||
|
nColumns,
|
|||
|
(pBinding?pBinding:prgBindings),
|
|||
|
0,
|
|||
|
phAccessor,
|
|||
|
NULL);
|
|||
|
|
|||
|
//
|
|||
|
// If a binding was created automatically, free it
|
|||
|
//
|
|||
|
if (prgBindings)
|
|||
|
{
|
|||
|
CoTaskMemFree(prgBindings);
|
|||
|
}
|
|||
|
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// FetchInstallData
|
|||
|
//-----------------
|
|||
|
//
|
|||
|
// This routine performs actual data access after a query execution.
|
|||
|
//
|
|||
|
// It is not generic. It is query specific.
|
|||
|
//
|
|||
|
// This routine fetches data for the most common package query.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
HRESULT FetchInstallData(
|
|||
|
IRowset *pIRowset,
|
|||
|
HACCESSOR hAccessor,
|
|||
|
QUERYCONTEXT *pQryContext,
|
|||
|
LPOLESTR pszFileExt,
|
|||
|
ULONG cRows,
|
|||
|
ULONG *pcRowsFetched,
|
|||
|
INSTALLINFO *pInstallInfo,
|
|||
|
UINT *pdwPriority
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
HROW * phRows = NULL;
|
|||
|
HRESULT hr;
|
|||
|
UINT i, j;
|
|||
|
Data pData[20];
|
|||
|
VARIANT *pVariant;
|
|||
|
ULONG cRowsGot;
|
|||
|
ULONG cPlatforms = 0;
|
|||
|
DWORD dwPlatformList[20];
|
|||
|
ULONG cLocale = 0;
|
|||
|
LCID dwLocaleList[20];
|
|||
|
CSPLATFORM PkgPlatform;
|
|||
|
|
|||
|
|
|||
|
*pcRowsFetched = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Get the rows
|
|||
|
//
|
|||
|
phRows = (HROW *) CoTaskMemAlloc (sizeof (HROW) * cRows);
|
|||
|
if(!phRows)
|
|||
|
{
|
|||
|
return E_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
hr = pIRowset->GetNextRows(NULL, 0, cRows, &cRowsGot, &phRows);
|
|||
|
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("IRowset::GetNextRows failed hr = 0x%x\n", hr);
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
for (i = 0; i < cRowsGot; i++)
|
|||
|
{
|
|||
|
//
|
|||
|
// Get the data from each row
|
|||
|
//
|
|||
|
|
|||
|
memset(pData, 0, sizeof(Data) * 20);
|
|||
|
|
|||
|
hr = pIRowset->GetData(phRows[i],
|
|||
|
hAccessor,
|
|||
|
(void*)&pData[0]
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
if (FAILED(hr))
|
|||
|
{
|
|||
|
//
|
|||
|
// BUGBUG. Missing cleanup.
|
|||
|
//
|
|||
|
printf("IRowset::GetData failed \n");
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If querying by file ext check match and priority
|
|||
|
// .
|
|||
|
|
|||
|
if (pszFileExt)
|
|||
|
{
|
|||
|
//Column = fileExtension
|
|||
|
|
|||
|
ULONG cFileExt = 20;
|
|||
|
LPOLESTR szFileExt[20], pStr;
|
|||
|
|
|||
|
if (pData[10].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
cFileExt = 20;
|
|||
|
pVariant = (VARIANT*) pData[10].obValue;
|
|||
|
hr = GetFromVariant(pVariant, &cFileExt, (LPOLESTR *)&szFileExt[0]);
|
|||
|
}
|
|||
|
|
|||
|
UINT cLen = wcslen(pszFileExt);
|
|||
|
for (j=0; j < cFileExt; ++j)
|
|||
|
{
|
|||
|
if (wcslen(szFileExt[j]) != (cLen+3))
|
|||
|
continue;
|
|||
|
if (wcsncmp(szFileExt[j], pszFileExt, wcslen(pszFileExt)) != 0)
|
|||
|
continue;
|
|||
|
*pdwPriority = wcstoul(szFileExt[j]+(cLen+1), &pStr, 10);
|
|||
|
break;
|
|||
|
}
|
|||
|
//
|
|||
|
// If none matched skip this package
|
|||
|
//
|
|||
|
if (j == cFileExt)
|
|||
|
continue;
|
|||
|
|
|||
|
}
|
|||
|
//
|
|||
|
// Now check Locale and Platform
|
|||
|
// .
|
|||
|
|
|||
|
if (pQryContext->Locale != LOCALE_NEUTRAL)
|
|||
|
{
|
|||
|
//Column = localeID
|
|||
|
|
|||
|
if (pData[7].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
cLocale = 20;
|
|||
|
pVariant = (VARIANT*) pData[7].obValue;
|
|||
|
hr = GetFromVariant(pVariant, &cLocale, (LPOLESTR *)&dwLocaleList[0]);
|
|||
|
}
|
|||
|
|
|||
|
for (j=0; j < cLocale; ++j)
|
|||
|
{
|
|||
|
if (MatchLocale (dwLocaleList[j], pQryContext->Locale))
|
|||
|
break;
|
|||
|
}
|
|||
|
//
|
|||
|
// If none matched skip this package
|
|||
|
//
|
|||
|
if (j == cLocale)
|
|||
|
continue;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//Column = machineArchitecture
|
|||
|
|
|||
|
if (pData[8].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
cPlatforms = 20;
|
|||
|
pVariant = (VARIANT*) pData[8].obValue;
|
|||
|
hr = GetFromVariant(pVariant, &cPlatforms, (LPOLESTR *)&dwPlatformList[0]);
|
|||
|
}
|
|||
|
|
|||
|
for (j=0; j < cPlatforms; ++j)
|
|||
|
{
|
|||
|
PackPlatform (dwPlatformList[j], &PkgPlatform);
|
|||
|
if (MatchPlatform (&(pQryContext->Platform), &PkgPlatform))
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If none matched skip this package
|
|||
|
//
|
|||
|
if (j == cPlatforms)
|
|||
|
continue;
|
|||
|
|
|||
|
//
|
|||
|
// Move the data into InstallInfo structure
|
|||
|
//
|
|||
|
|
|||
|
memset(pInstallInfo, 0, sizeof(INSTALLINFO));
|
|||
|
|
|||
|
//Column = packageFlags
|
|||
|
if (pData[1].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pInstallInfo->dwActFlags = (ULONG) (pData[1].obValue);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Does it support AutoInstall?
|
|||
|
//
|
|||
|
if (!(pInstallInfo->dwActFlags & ACTFLG_OnDemandInstall))
|
|||
|
continue;
|
|||
|
|
|||
|
//Column = codePackage
|
|||
|
if (pData[0].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pInstallInfo->pszScriptPath = (LPWSTR) CoTaskMemAlloc
|
|||
|
(sizeof(WCHAR) * (wcslen ((WCHAR *)pData[0].obValue)+1));
|
|||
|
wcscpy (pInstallInfo->pszScriptPath, (WCHAR *) pData[0].obValue);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//Column = comClassID
|
|||
|
if (pData[2].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
ULONG cCount = 1;
|
|||
|
LPOLESTR pList = NULL;
|
|||
|
|
|||
|
pVariant = (VARIANT*) pData[2].obValue;
|
|||
|
// Only access the first entry
|
|||
|
hr = GetFromVariant(pVariant, &cCount, &pList);
|
|||
|
pInstallInfo->pClsid = (GUID *) CoTaskMemAlloc (sizeof (GUID));
|
|||
|
GUIDFromString(pList, pInstallInfo->pClsid);
|
|||
|
CoTaskMemFree (pList);
|
|||
|
}
|
|||
|
|
|||
|
//Column = packageType
|
|||
|
if (pData[3].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pInstallInfo->PathType = (CLASSPATHTYPE) (ULONG) (pData[3].obValue);
|
|||
|
}
|
|||
|
|
|||
|
//Column = lastUpdateSequence,
|
|||
|
if (pData[4].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
swscanf ((LPOLESTR)(pData[4].obValue),
|
|||
|
L"%d %d",
|
|||
|
&(((CSUSN *)&(pInstallInfo->Usn))->dwHighDateTime),
|
|||
|
&(((CSUSN *)&(pInstallInfo->Usn))->dwLowDateTime));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//Column = versionNumberHi
|
|||
|
if (pData[5].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pInstallInfo->dwVersionHi = (ULONG) (pData[5].obValue);
|
|||
|
}
|
|||
|
|
|||
|
//Column = versionNumberLo
|
|||
|
if (pData[6].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pInstallInfo->dwVersionLo = (ULONG) (pData[6].obValue);
|
|||
|
}
|
|||
|
|
|||
|
if (pData[11].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
ULONG cUp = 20;
|
|||
|
|
|||
|
pVariant = (VARIANT*) pData[11].obValue;
|
|||
|
pInstallInfo->prgUpgradeScript =
|
|||
|
(LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR) * cUp);
|
|||
|
hr = GetFromVariant(pVariant, &cUp, pInstallInfo->prgUpgradeScript);
|
|||
|
pInstallInfo->cUpgrades = cUp;
|
|||
|
|
|||
|
pInstallInfo->prgUpgradeFlag =
|
|||
|
(DWORD *) CoTaskMemAlloc(sizeof(DWORD) * cUp);
|
|||
|
|
|||
|
for (j=0; j < cUp; ++j)
|
|||
|
{
|
|||
|
LPOLESTR pStr;
|
|||
|
LPOLESTR ptr = (pInstallInfo->prgUpgradeScript)[j];
|
|||
|
UINT l = wcslen (ptr);
|
|||
|
*(ptr+l-2) = NULL;
|
|||
|
(pInstallInfo->prgUpgradeFlag)[j] = wcstoul(ptr+(l-1), &pStr, 10);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//Column = installUiLevel
|
|||
|
if (pData[12].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pInstallInfo->InstallUiLevel = (UINT) (pData[12].obValue);
|
|||
|
}
|
|||
|
|
|||
|
//Column = ComClassContext
|
|||
|
if (pData[13].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pInstallInfo->dwComClassContext = (UINT) (pData[13].obValue);
|
|||
|
}
|
|||
|
|
|||
|
//Column = HelpUrl
|
|||
|
if (pData[14].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
ULONG cCount = 1;
|
|||
|
|
|||
|
pVariant = (VARIANT*) pData[14].obValue;
|
|||
|
// access only the first entry, allocated.
|
|||
|
hr = GetFromVariant(pVariant, &cCount, &(pInstallInfo->pszUrl));
|
|||
|
}
|
|||
|
|
|||
|
//Column = setupCommand
|
|||
|
if (pData[15].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pInstallInfo->pszSetupCommand = (LPWSTR) CoTaskMemAlloc
|
|||
|
(sizeof(WCHAR) * (wcslen ((WCHAR *)pData[15].obValue)+1));
|
|||
|
wcscpy (pInstallInfo->pszSetupCommand, (WCHAR *) pData[15].obValue);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check what memory needs to be freed
|
|||
|
//
|
|||
|
++pInstallInfo;
|
|||
|
++pdwPriority;
|
|||
|
++(*pcRowsFetched);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (cRowsGot)
|
|||
|
{
|
|||
|
//
|
|||
|
// Free the Row Handles
|
|||
|
//
|
|||
|
hr = pIRowset->ReleaseRows(cRowsGot, phRows, NULL, NULL, NULL);
|
|||
|
}
|
|||
|
|
|||
|
if (phRows)
|
|||
|
{
|
|||
|
//
|
|||
|
// Free the Row Handle Pointer
|
|||
|
//
|
|||
|
CoTaskMemFree (phRows);
|
|||
|
}
|
|||
|
|
|||
|
return S_OK;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// FetchPackageInfo
|
|||
|
//-----------------
|
|||
|
//
|
|||
|
// This routine performs actual data access after a query execution.
|
|||
|
//
|
|||
|
// It is not generic. It is query specific.
|
|||
|
//
|
|||
|
// This routine fetches data for the most common package query.
|
|||
|
|
|||
|
|
|||
|
HRESULT FetchPackageInfo(IRowset *pIRowset,
|
|||
|
HACCESSOR hAccessor,
|
|||
|
DWORD dwFlags,
|
|||
|
DWORD *pdwLocale,
|
|||
|
CSPLATFORM *pPlatform,
|
|||
|
ULONG cRows,
|
|||
|
ULONG *pcRowsFetched,
|
|||
|
PACKAGEDISPINFO *pPackageInfo
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
HROW * phRows = NULL;
|
|||
|
HRESULT hr;
|
|||
|
UINT i, j;
|
|||
|
Data pData[20];
|
|||
|
VARIANT *pVariant;
|
|||
|
ULONG cPlatforms = 0;
|
|||
|
DWORD dwPlatformList[20];
|
|||
|
ULONG cOs = 0;
|
|||
|
DWORD dwOsList[20];
|
|||
|
ULONG cLocale = 0;
|
|||
|
LCID dwLocaleList[20];
|
|||
|
DWORD dwPackageFlags;
|
|||
|
ULONG cFetched;
|
|||
|
ULONG cRowsLeft;
|
|||
|
CSPLATFORM PkgPlatform;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Get the rows
|
|||
|
//
|
|||
|
phRows = (HROW *) CoTaskMemAlloc (sizeof (HROW) * cRows);
|
|||
|
if(!phRows)
|
|||
|
{
|
|||
|
return E_OUTOFMEMORY;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The LDAP filter performs a part of the selection
|
|||
|
// The flag filters are interpreted on the client after obtaining the result set
|
|||
|
// That requires us to repeat the fetch a number of times so as to
|
|||
|
// make sure that all requested items are obtained.
|
|||
|
//
|
|||
|
|
|||
|
*pcRowsFetched = 0;
|
|||
|
cRowsLeft = cRows;
|
|||
|
|
|||
|
while (TRUE)
|
|||
|
{
|
|||
|
hr = pIRowset->GetNextRows(NULL, 0, cRowsLeft, &cFetched, &phRows);
|
|||
|
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("IRowset::GetNextRows failed hr = 0x%x\n", hr);
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
for (i = 0; i < cFetched; i++)
|
|||
|
{
|
|||
|
//
|
|||
|
// Get the data from each row
|
|||
|
//
|
|||
|
|
|||
|
memset(pData, 0, sizeof(Data) * 20);
|
|||
|
|
|||
|
hr = pIRowset->GetData(phRows[i],
|
|||
|
hAccessor,
|
|||
|
(void*)&pData[0]
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
//
|
|||
|
// BUGBUG. Missing cleanup.
|
|||
|
//
|
|||
|
printf("IRowset::GetData failed \n");
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Check flag values to see if this package meets the filter
|
|||
|
//
|
|||
|
|
|||
|
//Get the Flag Value: Column = packageFlags
|
|||
|
|
|||
|
dwPackageFlags = 0;
|
|||
|
if (pData[1].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
dwPackageFlags = (ULONG) (pData[1].obValue);
|
|||
|
}
|
|||
|
|
|||
|
if ((dwFlags & APPINFO_PUBLISHED) && (!(dwPackageFlags & ACTFLG_Published)))
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if ((dwFlags & APPINFO_ASSIGNED) && (!(dwPackageFlags & ACTFLG_Assigned)))
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if ((dwFlags & APPINFO_VISIBLE) && (!(dwPackageFlags & ACTFLG_UserInstall)))
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if ((dwFlags & APPINFO_AUTOINSTALL) && (!(dwPackageFlags & ACTFLG_OnDemandInstall)))
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Move the data into PackageInfo structure
|
|||
|
//
|
|||
|
memset(pPackageInfo, 0, sizeof(PACKAGEDISPINFO));
|
|||
|
|
|||
|
//Column = packageType
|
|||
|
if (pData[2].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pPackageInfo->PathType = (CLASSPATHTYPE) (ULONG) (pData[2].obValue);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now check PathType
|
|||
|
//
|
|||
|
|
|||
|
if ((dwFlags & APPINFO_MSI) && (pPackageInfo->PathType != DrwFilePath))
|
|||
|
{
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now check Locale and Platform
|
|||
|
// BUGBUG. Missing.
|
|||
|
|
|||
|
|
|||
|
if (pdwLocale)
|
|||
|
{
|
|||
|
//Column = localeID
|
|||
|
|
|||
|
if (pData[8].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
cLocale = 20;
|
|||
|
pVariant = (VARIANT*) pData[8].obValue;
|
|||
|
hr = GetFromVariant(pVariant, &cLocale, (LPOLESTR *)&dwLocaleList[0]);
|
|||
|
}
|
|||
|
|
|||
|
for (j=0; j < cLocale; ++j)
|
|||
|
{
|
|||
|
if (MatchLocale (dwLocaleList[j], *pdwLocale))
|
|||
|
break;
|
|||
|
}
|
|||
|
//
|
|||
|
// If none matched skip this package
|
|||
|
//
|
|||
|
if (j == cLocale)
|
|||
|
continue;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (pPlatform != NULL)
|
|||
|
{
|
|||
|
|
|||
|
//Column = machineArchitecture
|
|||
|
|
|||
|
if (pData[9].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
cPlatforms = 20;
|
|||
|
pVariant = (VARIANT*) pData[9].obValue;
|
|||
|
hr = GetFromVariant(pVariant, &cPlatforms, (LPOLESTR *)&dwPlatformList[0]);
|
|||
|
}
|
|||
|
|
|||
|
//Column = oSVersion. BUGBUG - unused now
|
|||
|
|
|||
|
if (pData[10].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
cOs = 20;
|
|||
|
pVariant = (VARIANT*) pData[10].obValue;
|
|||
|
hr = GetFromVariant(pVariant, &cOs, (LPOLESTR *)&dwOsList[0]);
|
|||
|
}
|
|||
|
|
|||
|
for (j=0; j < cPlatforms; ++j)
|
|||
|
{
|
|||
|
PackPlatform (dwPlatformList[j], &PkgPlatform);
|
|||
|
if (MatchPlatform (pPlatform, &PkgPlatform))
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If none matched skip this package.
|
|||
|
//
|
|||
|
if (j == cPlatforms)
|
|||
|
continue;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pPackageInfo->dwActFlags = dwPackageFlags;
|
|||
|
|
|||
|
//Column = packageName
|
|||
|
if (pData[0].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pPackageInfo->pszPackageName = (LPWSTR) CoTaskMemAlloc
|
|||
|
(sizeof(WCHAR) * (wcslen ((WCHAR *)pData[0].obValue)+1));
|
|||
|
wcscpy (pPackageInfo->pszPackageName, (WCHAR *) pData[0].obValue);
|
|||
|
}
|
|||
|
|
|||
|
//Column = codePackage
|
|||
|
if (pData[3].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pPackageInfo->pszScriptPath = (LPWSTR) CoTaskMemAlloc
|
|||
|
(sizeof(WCHAR) * (wcslen ((WCHAR *)pData[3].obValue)+1));
|
|||
|
wcscpy (pPackageInfo->pszScriptPath, (WCHAR *) pData[3].obValue);
|
|||
|
}
|
|||
|
|
|||
|
//Column = cScriptLen
|
|||
|
// BUGBUG. Wait for pScript.
|
|||
|
if (pData[4].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pPackageInfo->cScriptLen = 0; //(ULONG) (pData[4].obValue);
|
|||
|
}
|
|||
|
|
|||
|
//Column = lastUpdateSequence,
|
|||
|
if (pData[5].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
swscanf ((LPOLESTR)(pData[5].obValue),
|
|||
|
L"%d %d",
|
|||
|
&(((CSUSN *)&(pPackageInfo->Usn))->dwHighDateTime),
|
|||
|
&(((CSUSN *)&(pPackageInfo->Usn))->dwLowDateTime));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//Column = versionNumberHi
|
|||
|
if (pData[6].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pPackageInfo->dwVersionHi = (ULONG) (pData[6].obValue);
|
|||
|
}
|
|||
|
|
|||
|
//Column = versionNumberLo
|
|||
|
if (pData[7].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
pPackageInfo->dwVersionLo = (ULONG) (pData[7].obValue);
|
|||
|
}
|
|||
|
|
|||
|
if (pData[11].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
ULONG cUp = 20;
|
|||
|
|
|||
|
pVariant = (VARIANT*) pData[11].obValue;
|
|||
|
pPackageInfo->prgUpgradeScript =
|
|||
|
(LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR) * cUp);
|
|||
|
hr = GetFromVariant(pVariant, &cUp, pPackageInfo->prgUpgradeScript);
|
|||
|
pPackageInfo->cUpgrades = cUp;
|
|||
|
|
|||
|
pPackageInfo->prgUpgradeFlag =
|
|||
|
(DWORD *) CoTaskMemAlloc(sizeof(DWORD) * cUp);
|
|||
|
|
|||
|
for (j=0; j < cUp; ++j)
|
|||
|
{
|
|||
|
LPOLESTR pStr;
|
|||
|
LPOLESTR ptr = (pPackageInfo->prgUpgradeScript)[j];
|
|||
|
UINT l = wcslen (ptr);
|
|||
|
*(ptr+l-2) = NULL;
|
|||
|
(pPackageInfo->prgUpgradeFlag)[j] =
|
|||
|
wcstoul(ptr+(l-1), &pStr, 10);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now process inline filters to decide if this package
|
|||
|
// meets the filter requirements
|
|||
|
// BUGBUG. Not implemented.
|
|||
|
if (0)
|
|||
|
{
|
|||
|
PackPlatform (dwPlatformList[0], NULL);
|
|||
|
}
|
|||
|
++pPackageInfo;
|
|||
|
|
|||
|
(*pcRowsFetched)++;
|
|||
|
|
|||
|
//
|
|||
|
// Release memory
|
|||
|
//
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (cFetched)
|
|||
|
{
|
|||
|
//
|
|||
|
// Free the Row Handles
|
|||
|
//
|
|||
|
hr = pIRowset->ReleaseRows(cFetched, phRows, NULL, NULL, NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (cRowsLeft > cFetched)
|
|||
|
{
|
|||
|
hr = S_FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
cRowsLeft = cRows - *pcRowsFetched;
|
|||
|
|
|||
|
if (cRowsLeft == 0)
|
|||
|
{
|
|||
|
hr = S_OK;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (phRows)
|
|||
|
{
|
|||
|
//
|
|||
|
// Free the Row Handle Pointer
|
|||
|
//
|
|||
|
CoTaskMemFree (phRows);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check if we found as many as asked for
|
|||
|
//
|
|||
|
//if (*pcRowsFetched != cRows)
|
|||
|
// return S_FALSE;
|
|||
|
return hr;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// FetchCategory
|
|||
|
//--------------
|
|||
|
//
|
|||
|
// List of columns this routine fetches.
|
|||
|
//
|
|||
|
|
|||
|
LPOLESTR szAppCategoryColumns =
|
|||
|
L"extensionName, categoryId";
|
|||
|
|
|||
|
HRESULT FetchCategory(IRowset * pIRowset,
|
|||
|
HACCESSOR hAccessor,
|
|||
|
ULONG cRows,
|
|||
|
ULONG * pcRowsFetched,
|
|||
|
APPCATEGORYINFO ** ppCategory,
|
|||
|
LCID Locale
|
|||
|
)
|
|||
|
{
|
|||
|
HROW * phRows = NULL;
|
|||
|
HRESULT hr = S_OK;
|
|||
|
UINT i;
|
|||
|
Data pData[20];
|
|||
|
VARIANT * pVariant = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Get the rows
|
|||
|
//
|
|||
|
|
|||
|
// phRows = (HROW *) CoTaskMemAlloc (sizeof (HROW) * cRows);
|
|||
|
// if(!phRows)
|
|||
|
// {
|
|||
|
// return E_OUTOFMEMORY;
|
|||
|
// }
|
|||
|
//
|
|||
|
// hr = pIRowset->GetNextRows(NULL, 0, cRows, pcRowsFetched, &phRows);
|
|||
|
|
|||
|
phRows = NULL;
|
|||
|
|
|||
|
hr = pIRowset->GetNextRows(NULL, 0, cRows, pcRowsFetched, &phRows);
|
|||
|
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("IRowset::GetNextRows failed hr = 0x%x\n", hr);
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
if (*pcRowsFetched)
|
|||
|
*ppCategory = (APPCATEGORYINFO *)CoTaskMemAlloc(sizeof(APPCATEGORYINFO)*
|
|||
|
(*pcRowsFetched));
|
|||
|
for (i = 0; i < *pcRowsFetched; i++)
|
|||
|
{
|
|||
|
//
|
|||
|
// Get the data from each row
|
|||
|
//
|
|||
|
|
|||
|
memset(pData, 0, sizeof(Data));
|
|||
|
|
|||
|
hr = pIRowset->GetData(phRows[i],
|
|||
|
hAccessor,
|
|||
|
(void*)&pData[0]
|
|||
|
);
|
|||
|
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
//
|
|||
|
// BUGBUG. Missing cleanup.
|
|||
|
//
|
|||
|
printf("IRowset::GetData failed \n");
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
//Column = description
|
|||
|
|
|||
|
if (pData[0].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
ULONG cCount = 20;
|
|||
|
LPOLESTR pszDesc[20];
|
|||
|
|
|||
|
pVariant = (VARIANT*) pData[0].obValue;
|
|||
|
|
|||
|
hr = GetFromVariant(pVariant, &cCount, (LPOLESTR *)&pszDesc[0]);
|
|||
|
|
|||
|
(*ppCategory)[i].Locale = Locale;
|
|||
|
(*ppCategory)[i].pszDescription = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*128);
|
|||
|
// BUGBUG:: same as comcat size. an arbitrary restriction.
|
|||
|
|
|||
|
hr = GetCategoryLocaleDesc(pszDesc, cCount, &((*ppCategory)[i].Locale),
|
|||
|
(*ppCategory)[i].pszDescription);
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// column catid
|
|||
|
if (pData[1].status != DBSTATUS_S_ISNULL)
|
|||
|
{
|
|||
|
GUIDFromString((LPOLESTR)pData[1].obValue, &((*ppCategory)[i].AppCategoryId));
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (*pcRowsFetched)
|
|||
|
{
|
|||
|
//
|
|||
|
// Free the Row Handles
|
|||
|
//
|
|||
|
hr = pIRowset->ReleaseRows(*pcRowsFetched, phRows, NULL, NULL, NULL);
|
|||
|
}
|
|||
|
|
|||
|
if (*pcRowsFetched)
|
|||
|
{
|
|||
|
//
|
|||
|
// Free the Row Handle Pointer
|
|||
|
//
|
|||
|
CoTaskMemFree (phRows);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check if we found as many as asked for
|
|||
|
//
|
|||
|
if (*pcRowsFetched != cRows)
|
|||
|
return S_FALSE;
|
|||
|
return S_OK;
|
|||
|
}
|
|||
|
|
|||
|
HRESULT CloseQuery(IAccessor *pAccessor,
|
|||
|
HACCESSOR hAccessor,
|
|||
|
IRowset *pIRowset)
|
|||
|
{
|
|||
|
ULONG cRef;
|
|||
|
|
|||
|
if (pAccessor)
|
|||
|
{
|
|||
|
pAccessor->ReleaseAccessor(hAccessor, &cRef);
|
|||
|
pAccessor->Release();
|
|||
|
}
|
|||
|
|
|||
|
if (pIRowset)
|
|||
|
{
|
|||
|
pIRowset->Release();
|
|||
|
}
|
|||
|
|
|||
|
return S_OK;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//---------------------------------------------------------------
|
|||
|
// End of Query
|
|||
|
//----------------------------------------------------------------
|
|||
|
|
|||
|
//
|
|||
|
// Form the bindings array to specify the way the provider has to put the
|
|||
|
// data in buffer.
|
|||
|
//
|
|||
|
|
|||
|
UINT i;
|
|||
|
HRESULT
|
|||
|
CreateBindingHelper(
|
|||
|
IRowset *pIRowset,
|
|||
|
ULONG cColumns,
|
|||
|
DBBINDING **pprgBind
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
HRESULT hr;
|
|||
|
ULONG cCols;
|
|||
|
DBCOLUMNINFO *prgColInfo = NULL;
|
|||
|
IColumnsInfo *pIColsInfo = NULL;
|
|||
|
LPOLESTR szColNames = NULL;
|
|||
|
DBBINDING *prgBindings = NULL;
|
|||
|
|
|||
|
if(!pIRowset)
|
|||
|
return(E_INVALIDARG);
|
|||
|
|
|||
|
hr = pIRowset->QueryInterface(
|
|||
|
IID_IColumnsInfo,
|
|||
|
(void**) &pIColsInfo
|
|||
|
);
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("QueryInterface for IColumnsInfo failed \n");
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
hr = pIColsInfo->GetColumnInfo(
|
|||
|
&cCols,
|
|||
|
&prgColInfo,
|
|||
|
&szColNames
|
|||
|
);
|
|||
|
if(FAILED(hr))
|
|||
|
{
|
|||
|
printf("IColumnsInfo::GetColumnInfo failed \n");
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Verify that the number of columns match
|
|||
|
//
|
|||
|
if (cColumns != (cCols - 1))
|
|||
|
{
|
|||
|
return E_FAIL;
|
|||
|
}
|
|||
|
|
|||
|
prgBindings = (DBBINDING *) CoTaskMemAlloc(sizeof(DBBINDING) * cColumns);
|
|||
|
|
|||
|
//
|
|||
|
// Set up rest of the attributes
|
|||
|
//
|
|||
|
for (i=0; i < cColumns; i++)
|
|||
|
{
|
|||
|
memset (prgBindings+i, 0, sizeof(DBBINDING));
|
|||
|
prgBindings[i].iOrdinal = i+1;
|
|||
|
prgBindings[i].wType= prgColInfo[i+1].wType;
|
|||
|
if ((prgBindings[i].wType == DBTYPE_DATE) || (prgBindings[i].wType == DBTYPE_I8))
|
|||
|
prgBindings[i].obValue = sizeof(Data)*i + offsetof(Data, obValue2);
|
|||
|
else
|
|||
|
prgBindings[i].obValue = sizeof(Data)*i + offsetof(Data, obValue);
|
|||
|
prgBindings[i].obLength= sizeof(Data)*i + offsetof(Data, obLength);
|
|||
|
prgBindings[i].obStatus= sizeof(Data)*i + offsetof(Data, status);
|
|||
|
prgBindings[i].dwPart= DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS;
|
|||
|
|
|||
|
if(prgBindings[i].wType & DBTYPE_BYREF)
|
|||
|
prgBindings[i].dwMemOwner= DBMEMOWNER_PROVIDEROWNED;
|
|||
|
else
|
|||
|
prgBindings[i].dwMemOwner= DBMEMOWNER_CLIENTOWNED;
|
|||
|
|
|||
|
prgBindings[i].dwFlags= 0;
|
|||
|
}
|
|||
|
|
|||
|
*pprgBind = prgBindings;
|
|||
|
|
|||
|
pIColsInfo->Release();
|
|||
|
|
|||
|
CoTaskMemFree(szColNames);
|
|||
|
CoTaskMemFree(prgColInfo);
|
|||
|
|
|||
|
return(hr);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
//
|
|||
|
void GetCurrentUsn(LPOLESTR pStoreUsn)
|
|||
|
{
|
|||
|
//
|
|||
|
// Get the current time as USN for the Class Store container
|
|||
|
//
|
|||
|
SYSTEMTIME SystemTime;
|
|||
|
|
|||
|
GetSystemTime(&SystemTime);
|
|||
|
|
|||
|
wsprintf (pStoreUsn, L"%4d%2d%2d%2d%2d%2d",
|
|||
|
SystemTime.wYear,
|
|||
|
SystemTime.wMonth,
|
|||
|
SystemTime.wDay,
|
|||
|
SystemTime.wHour,
|
|||
|
SystemTime.wMinute,
|
|||
|
SystemTime.wSecond);
|
|||
|
|
|||
|
}
|
|||
|
//
|
|||
|
|
|||
|
HRESULT UsnUpd (IADs *pADs, LPWSTR szProp, LPOLESTR pUsn)
|
|||
|
{
|
|||
|
//
|
|||
|
// Store the current USN
|
|||
|
//
|
|||
|
|
|||
|
HRESULT hr = SetProperty (pADs,
|
|||
|
szProp,
|
|||
|
pUsn);
|
|||
|
|
|||
|
return S_OK;
|
|||
|
}
|
|||
|
|
|||
|
HRESULT UsnGet(IADs *pADs, LPWSTR szProp, CSUSN *pUsn)
|
|||
|
{
|
|||
|
//
|
|||
|
// Read the USN for the Class Store container or Package
|
|||
|
//
|
|||
|
WCHAR szTimeStamp [20];
|
|||
|
SYSTEMTIME SystemTime;
|
|||
|
|
|||
|
GetProperty (pADs,
|
|||
|
szProp,
|
|||
|
szTimeStamp);
|
|||
|
|
|||
|
swscanf (szTimeStamp, L"%4d%2d%2d%2d%2d%2d",
|
|||
|
&SystemTime.wYear,
|
|||
|
&SystemTime.wMonth,
|
|||
|
&SystemTime.wDay,
|
|||
|
&SystemTime.wHour,
|
|||
|
&SystemTime.wMinute,
|
|||
|
&SystemTime.wSecond);
|
|||
|
|
|||
|
SystemTimeToFileTime(&SystemTime,
|
|||
|
(LPFILETIME) pUsn);
|
|||
|
|
|||
|
return S_OK;
|
|||
|
}
|
|||
|
|
|||
|
HRESULT GetPackageDetail (IADs *pPackageADs,
|
|||
|
PACKAGEDETAIL *pPackageDetail)
|
|||
|
{
|
|||
|
HRESULT hr = S_OK;
|
|||
|
GUID PkgGuid;
|
|||
|
LPOLESTR *pszString = NULL;
|
|||
|
DWORD *pdwArch = NULL, count;
|
|||
|
PLATFORMINFO *pPlatformInfo;
|
|||
|
INSTALLINFO *pInstallInfo;
|
|||
|
ACTIVATIONINFO *pActInfo;
|
|||
|
DWORD cClasses;
|
|||
|
LPOLESTR *szClasses;
|
|||
|
DWORD dwUiLevel;
|
|||
|
|
|||
|
|
|||
|
memset (pPackageDetail, 0, sizeof (PACKAGEDETAIL));
|
|||
|
|
|||
|
pInstallInfo = pPackageDetail->pInstallInfo = (INSTALLINFO *) CoTaskMemAlloc(sizeof (INSTALLINFO));
|
|||
|
|
|||
|
if (pInstallInfo)
|
|||
|
{
|
|||
|
memset(pInstallInfo, NULL, sizeof(INSTALLINFO));
|
|||
|
|
|||
|
hr = GetPropertyDW (pPackageADs, PACKAGEFLAGS,
|
|||
|
&(pInstallInfo->dwActFlags));
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyDW (pPackageADs, PACKAGETYPE,
|
|||
|
(DWORD *)&(pInstallInfo->PathType));
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyAlloc(pPackageADs, SCRIPTPATH,
|
|||
|
&(pInstallInfo->pszScriptPath));
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
// BUGBUG. Wait for pScript
|
|||
|
//hr = GetPropertyDW (pPackageADs, SCRIPTSIZE,
|
|||
|
// &(pInstallInfo->cScriptLen));
|
|||
|
//ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyAlloc(pPackageADs, SETUPCOMMAND,
|
|||
|
&(pInstallInfo->pszSetupCommand));
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyAlloc(pPackageADs, HELPURL,
|
|||
|
&(pInstallInfo->pszUrl));
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = UsnGet(pPackageADs,
|
|||
|
PKGUSN,
|
|||
|
(CSUSN *)&(pInstallInfo->Usn));
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyDW (pPackageADs, CLASSCTX,
|
|||
|
&(pInstallInfo->dwComClassContext));
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
// BUGBUG::***ProductCode
|
|||
|
|
|||
|
hr = GetPropertyDW (pPackageADs, VERSIONHI,
|
|||
|
&(pInstallInfo->dwVersionHi));
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyDW (pPackageADs, VERSIONLO,
|
|||
|
&(pInstallInfo->dwVersionLo));
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyDW (pPackageADs, UILEVEL,
|
|||
|
&dwUiLevel);
|
|||
|
pInstallInfo->InstallUiLevel = dwUiLevel;
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyListAlloc(pPackageADs,
|
|||
|
UPGRADESCRIPTNAMES,
|
|||
|
&count,
|
|||
|
&(pInstallInfo->prgUpgradeScript));
|
|||
|
pInstallInfo->prgUpgradeFlag = (DWORD *)CoTaskMemAlloc(count*sizeof(DWORD));
|
|||
|
pInstallInfo->cUpgrades = count;
|
|||
|
for (count = 0; (count < (pInstallInfo->cUpgrades)); count++)
|
|||
|
{
|
|||
|
LPOLESTR pStr = NULL;
|
|||
|
LPOLESTR ptr = (pInstallInfo->prgUpgradeScript)[count];
|
|||
|
UINT l = wcslen (ptr);
|
|||
|
*(ptr + l - 2) = NULL;
|
|||
|
(pInstallInfo->prgUpgradeFlag)[count] = wcstoul(ptr+(l-1), &pStr, 10);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
pPlatformInfo = pPackageDetail->pPlatformInfo =
|
|||
|
(PLATFORMINFO *) CoTaskMemAlloc(sizeof (PLATFORMINFO));
|
|||
|
|
|||
|
if (pPlatformInfo)
|
|||
|
{
|
|||
|
memset(pPlatformInfo, NULL, sizeof(PLATFORMINFO));
|
|||
|
|
|||
|
hr = GetPropertyListAllocDW(pPackageADs, ARCHLIST,
|
|||
|
(DWORD *)&(pPlatformInfo->cPlatforms), &pdwArch);
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
pPlatformInfo->prgPlatform = (CSPLATFORM *)CoTaskMemAlloc(sizeof(CSPLATFORM)*
|
|||
|
(pPlatformInfo->cPlatforms));
|
|||
|
|
|||
|
for (count = 0; (count < (pPlatformInfo->cPlatforms)); count++)
|
|||
|
PackPlatform (pdwArch[count], (pPlatformInfo->prgPlatform)+count);
|
|||
|
|
|||
|
CoTaskMemFree(pdwArch);
|
|||
|
|
|||
|
hr = GetPropertyListAllocDW (pPackageADs, LOCALEID,
|
|||
|
(DWORD *)&(pPlatformInfo->cLocales),
|
|||
|
&(pPlatformInfo->prgLocale));
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// fill in ActivationInfo.
|
|||
|
//
|
|||
|
pActInfo = pPackageDetail->pActInfo =
|
|||
|
(ACTIVATIONINFO *) CoTaskMemAlloc(sizeof (ACTIVATIONINFO));
|
|||
|
|
|||
|
if (pActInfo)
|
|||
|
{
|
|||
|
memset(pActInfo, NULL, sizeof(ACTIVATIONINFO));
|
|||
|
|
|||
|
hr = GetPropertyListAlloc(pPackageADs, PKGCLSIDLIST, &cClasses, &szClasses);
|
|||
|
pActInfo->cClasses = cClasses;
|
|||
|
if (cClasses)
|
|||
|
{
|
|||
|
pActInfo->pClasses = (CLASSDETAIL *) CoTaskMemAlloc (cClasses * sizeof(CLASSDETAIL));
|
|||
|
memset (pActInfo->pClasses, NULL, cClasses * sizeof(CLASSDETAIL));
|
|||
|
|
|||
|
for (count = 0; count < cClasses; count++)
|
|||
|
{
|
|||
|
GUIDFromString(szClasses[count], &((pActInfo->pClasses[count]).Clsid));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (count = 0; count < cClasses; count++)
|
|||
|
CoTaskMemFree(szClasses[count]);
|
|||
|
CoTaskMemFree(szClasses);
|
|||
|
|
|||
|
hr = GetPropertyListAlloc(pPackageADs, PKGIIDLIST, &cClasses, &szClasses);
|
|||
|
pActInfo->cInterfaces = cClasses;
|
|||
|
if (cClasses)
|
|||
|
{
|
|||
|
pActInfo->prgInterfaceId = (IID *) CoTaskMemAlloc (cClasses * sizeof(GUID));
|
|||
|
|
|||
|
for (count = 0; count < cClasses; count++)
|
|||
|
{
|
|||
|
GUIDFromString(szClasses[count], (pActInfo->prgInterfaceId + count));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (count = 0; count < cClasses; count++)
|
|||
|
CoTaskMemFree(szClasses[count]);
|
|||
|
CoTaskMemFree(szClasses);
|
|||
|
|
|||
|
hr = GetPropertyListAlloc(pPackageADs, PKGTLBIDLIST, &cClasses, &szClasses);
|
|||
|
pActInfo->cTypeLib = cClasses;
|
|||
|
if (cClasses)
|
|||
|
{
|
|||
|
pActInfo->prgTlbId = (GUID *) CoTaskMemAlloc (cClasses * sizeof(GUID));
|
|||
|
|
|||
|
for (count = 0; count < cClasses; count++)
|
|||
|
{
|
|||
|
GUIDFromString(szClasses[count], (pActInfo->prgTlbId + count));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (count = 0; count < cClasses; count++)
|
|||
|
CoTaskMemFree(szClasses[count]);
|
|||
|
CoTaskMemFree(szClasses);
|
|||
|
|
|||
|
hr = GetPropertyListAlloc(pPackageADs, PKGFILEEXTNLIST, &cClasses,
|
|||
|
&(pActInfo->prgShellFileExt));
|
|||
|
pActInfo->cShellFileExt = cClasses;
|
|||
|
if (cClasses)
|
|||
|
{
|
|||
|
pActInfo->prgPriority = (UINT *)CoTaskMemAlloc(cClasses * sizeof(UINT));
|
|||
|
for (count = 0; count < cClasses; count++)
|
|||
|
{
|
|||
|
LPOLESTR pStr;
|
|||
|
UINT cLen = wcslen((pActInfo->prgShellFileExt)[count]);
|
|||
|
*((pActInfo->prgShellFileExt)[count] + (cLen - 3)) = NULL;
|
|||
|
(pActInfo->prgPriority)[count] =
|
|||
|
wcstoul((pActInfo->prgShellFileExt)[count]+(cLen-2), &pStr, 10);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// fill in package misc info
|
|||
|
//
|
|||
|
hr = GetPropertyAlloc(pPackageADs, PACKAGENAME,
|
|||
|
&(pPackageDetail->pszPackageName));
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyListAlloc(pPackageADs, MSIFILELIST, &cClasses,
|
|||
|
&(pPackageDetail->pszSourceList));
|
|||
|
pPackageDetail->cSources = cClasses;
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
hr = GetPropertyListAlloc(pPackageADs, PKGCATEGORYLIST,
|
|||
|
&cClasses, &szClasses);
|
|||
|
ERROR_ON_FAILURE(hr);
|
|||
|
|
|||
|
if (cClasses)
|
|||
|
{
|
|||
|
pPackageDetail->rpCategory = (GUID *)CoTaskMemAlloc (sizeof(GUID) * cClasses);
|
|||
|
pPackageDetail->cCategories = cClasses;
|
|||
|
for (count = 0; count < cClasses; count++)
|
|||
|
{
|
|||
|
GUIDFromString(szClasses[count], (pPackageDetail->rpCategory + count));
|
|||
|
CoTaskMemFree(szClasses[count]);
|
|||
|
}
|
|||
|
CoTaskMemFree(szClasses);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
Error_Cleanup:
|
|||
|
|
|||
|
// BUGBUG:: free each of the strings.
|
|||
|
if (pszString)
|
|||
|
CoTaskMemFree(pszString);
|
|||
|
|
|||
|
pPackageADs->Release();
|
|||
|
return hr;
|
|||
|
}
|
|||
|
|
|||
|
|