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