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;
|
||
}
|
||
|
||
|