//*************************************************************************** // // (c) 1999-2001 by Microsoft Corp. All Rights Reserved. // // ESEUTILS.cpp // // cvadai 6-May-1999 created. // //*************************************************************************** // #define OBJECT_BLOB_CRC #define _JET_PROCS_CPP_ #pragma warning( disable : 4786 ) // identifier was truncated to 'number' characters in the #pragma warning( disable : 4251 ) // needs to have dll-interface to be used by clients of class #include "precomp.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_STRING_WIDTH 255 #define OBJECTMAP_COL_OBJECTID 1 #define OBJECTMAP_COL_OBJECTPATH 2 #define OBJECTMAP_COL_OBJECTKEY 3 #define OBJECTMAP_COL_REFERENCECOUNT 4 #define OBJECTMAP_COL_OBJECTSTATE 5 #define OBJECTMAP_COL_CLASSID 6 #define OBJECTMAP_COL_OBJECTFLAGS 7 #define OBJECTMAP_COL_OBJECTSCOPEID 8 #define CLASSMAP_COL_CLASSID 1 #define CLASSMAP_COL_CLASSNAME 2 #define CLASSMAP_COL_SUPERCLASSID 3 #define CLASSMAP_COL_DYNASTYID 4 #define CLASSMAP_COL_CLASSBUFFER 5 #define PROPERTYMAP_COL_CLASSID 1 #define PROPERTYMAP_COL_PROPERTYID 2 #define PROPERTYMAP_COL_STORAGETYPEID 3 #define PROPERTYMAP_COL_CIMTYPEID 4 #define PROPERTYMAP_COL_PROPERTYNAME 5 #define PROPERTYMAP_COL_FLAGS 6 #define PROPERTYMAP_COL_REFCLASSID 7 #define CLASSKEYS_COL_CLASSID 1 #define CLASSKEYS_COL_PROPERTYID 2 #define REFPROPS_COL_CLASSID 1 #define REFPROPS_COL_PROPERTYID 2 #define REFPROPS_COL_REFCLASSID 3 #define CLASSDATA_COL_OBJECTID 1 #define CLASSDATA_COL_PROPERTYID 2 #define CLASSDATA_COL_ARRAYPOS 3 #define CLASSDATA_COL_QFRPOS 4 #define CLASSDATA_COL_CLASSID 5 #define CLASSDATA_COL_STRINGVALUE 6 #define CLASSDATA_COL_NUMERICVALUE 7 #define CLASSDATA_COL_REFID 8 #define CLASSDATA_COL_REALVALUE 9 #define CLASSDATA_COL_REFCLASSID 10 #define CLASSDATA_COL_FLAGS 11 #define CLASSIMAGES_COL_OBJECTID 1 #define CLASSIMAGES_COL_PROPERTYID 2 #define CLASSIMAGES_COL_ARRAYPOS 3 #define CLASSIMAGES_COL_IMAGEVALUE 4 #define INDEXTBL_COL_OBJECTID 1 #define INDEXTBL_COL_PROPERTYID 2 #define INDEXTBL_COL_ARRAYPOS 3 #define INDEXTBL_COL_INDEXVALUE 4 #define CONTAINEROBJS_COL_CONTAINERID 1 #define CONTAINEROBJS_COL_CONTAINEEID 2 #define AUTODELETE_COL_OBJECTID 1 #define SCOPEMAP_COL_OBJECTID 1 #define SCOPEMAP_COL_SCOPEPATH 2 #define SCOPEMAP_COL_PARENTID 3 typedef std::vector SQLIDs; typedef std::vector IDs; typedef std::vector <_bstr_t> _bstr_ts; typedef std::map Properties; JET_INSTANCE gJetInst = NULL; typedef std::map SessionDynasties; LPWSTR StripQuotes2(LPWSTR lpText) { wchar_t *pszTemp = new wchar_t [wcslen(lpText)+1]; if (pszTemp) { int iPos = 0; BOOL bOnQuote = FALSE; int iLen = wcslen(lpText); if (iLen) { for (int i = 0; i < iLen; i++) { WCHAR t = lpText[i]; if (t == '\'') { if (!bOnQuote) { if (lpText[i+1] == '\'') { bOnQuote = TRUE; continue; } } } bOnQuote = FALSE; pszTemp[iPos] = t; iPos++; } } pszTemp[iPos] = '\0'; } return pszTemp; } void FreeBstr(BSTR * ppStr) { if (ppStr) { SysFreeString(*ppStr); *ppStr = NULL; } } HRESULT LoadSchemaProperties (CSQLConnection *pConn, CSchemaCache *pCache, SQL_ID dClassId) { // Enumerate properties HRESULT hr = WBEM_S_NO_ERROR; PROPERTYMAP pm; hr = GetFirst_PropertyMapByClass(pConn, dClassId, pm); while (SUCCEEDED(hr)) { hr = pCache->AddPropertyInfo (pm.iPropertyId, pm.sPropertyName, pm.dClassId, pm.iStorageTypeId, pm.iCIMTypeId, pm.iFlags, 0, L"", 0, 0); if (FAILED(hr)) { pm.Clear(); break; } hr = GetNext_PropertyMap(pConn, pm); } CLASSKEYS ck; hr = GetFirst_ClassKeys (pConn, dClassId, ck); while (SUCCEEDED(hr)) { pCache->SetIsKey(ck.dClassId, ck.iPropertyId); hr = GetNext_ClassKeys(pConn, ck); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; return hr; } //*************************************************************************** // // CWmiDbController::GetLogonTemplate // //*************************************************************************** HRESULT STDMETHODCALLTYPE CWmiDbController::GetLogonTemplate( /* [in] */ LCID lLocale, /* [in] */ DWORD dwFlags, /* [out] */ WMIDB_LOGON_TEMPLATE __RPC_FAR *__RPC_FAR *ppTemplate) { HRESULT hr = WBEM_S_NO_ERROR; if (dwFlags != 0 || !ppTemplate) return WBEM_E_INVALID_PARAMETER; try { if (ppTemplate) { WMIDB_LOGON_TEMPLATE *pTemp = new WMIDB_LOGON_TEMPLATE; if (pTemp) { pTemp->dwArraySize = 5; HINSTANCE hRCDll = GetResourceDll(lLocale); if (!hRCDll) { LCID lTemp = GetUserDefaultLangID(); hRCDll = GetResourceDll(lTemp); if (!hRCDll) { lTemp = GetSystemDefaultLangID(); hRCDll = GetResourceDll(lTemp); if (!hRCDll) hRCDll = LoadLibrary(L"reprc.dll"); // Last resort - try the current directory. } } wchar_t wDB[101], wUser[101], wPwd[101], wLocale[101], wMode[101]; pTemp->pParm = new WMIDB_LOGON_PARAMETER[6]; if (pTemp->pParm) { if (hRCDll) { LoadString(hRCDll, IDS_WMI_USER_NAME, wUser, 100); LoadString(hRCDll, IDS_WMI_PASSWORD, wPwd, 100); LoadString(hRCDll, IDS_WMI_DATABASE, wDB, 100); LoadString(hRCDll, IDS_WMI_LOCALE, wLocale, 100); LoadString(hRCDll, IDS_WMI_READMODE, wMode, 100); FreeLibrary(hRCDll); } else { wcscpy(wDB, L"Database"); wcscpy(wUser, L"UserID"); wcscpy(wPwd, L"Password"); wcscpy(wLocale, L"Locale"); wcscpy(wMode, L"Access Mode"); } pTemp->pParm[0].dwId = DBPROP_INIT_MODE; pTemp->pParm[0].strParmDisplayName = SysAllocString(wMode); VariantInit(&(pTemp->pParm[0].Value)); pTemp->pParm[0].Value.vt = VT_I4; pTemp->pParm[0].Value.lVal = DB_MODE_READWRITE ; pTemp->pParm[1].dwId = DBPROP_AUTH_USERID; pTemp->pParm[1].strParmDisplayName = SysAllocString(wUser); VariantInit(&(pTemp->pParm[1].Value)); pTemp->pParm[2].dwId = DBPROP_AUTH_PASSWORD; pTemp->pParm[2].strParmDisplayName = SysAllocString(wPwd); VariantInit(&(pTemp->pParm[2].Value)); pTemp->pParm[3].dwId = DBPROP_INIT_DATASOURCE; pTemp->pParm[3].strParmDisplayName = SysAllocString(wDB); VariantInit(&(pTemp->pParm[3].Value)); pTemp->pParm[4].dwId = DBPROP_INIT_LCID; pTemp->pParm[4].strParmDisplayName = SysAllocString(wLocale); VariantInit(&(pTemp->pParm[4].Value)); pTemp->pParm[4].Value.lVal = lLocale; pTemp->pParm[4].Value.vt = VT_I4; *ppTemplate = pTemp; } else { delete pTemp; hr = WBEM_E_OUT_OF_MEMORY; } } else hr = WBEM_E_OUT_OF_MEMORY; } else hr = WBEM_E_INVALID_PARAMETER; } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbController::GetLogonTemplate\n")); hr = WBEM_E_CRITICAL_ERROR; } return hr; } //*************************************************************************** // // GetPath // //*************************************************************************** LPWSTR GetPath (LPCWSTR lpDatabaseName) { wchar_t *pPath = NULL; if (lpDatabaseName && wcslen(lpDatabaseName)) { pPath = new wchar_t [(wcslen(lpDatabaseName))+1]; if (pPath) { BOOL bDone = FALSE; wchar_t *Temp = new wchar_t [wcslen(lpDatabaseName)+1]; if (Temp) { CDeleteMe d2 (Temp); wcscpy(Temp, lpDatabaseName); wchar_t *pTemp = wcsstr(Temp, L"\\"); while (!bDone) { pTemp++; wchar_t *pTemp2 = wcsstr(pTemp, L"\\"); if (!pTemp2) { bDone = TRUE; int iLen = (pTemp - Temp); wcsncpy(pPath, Temp, iLen); pPath[iLen] = L'\0'; break; } else pTemp = pTemp2; } } } } return pPath; } //*************************************************************************** // // DeleteDatabase // //*************************************************************************** HRESULT DeleteDatabase(LPCWSTR lpDatabaseName) { HRESULT hr = WBEM_S_NO_ERROR; // Enumerate all files in the directory // and delete them all // Also check if there are any conflictingly-named // subdirectories. ERRORTRACE((LOG_WBEMCORE, "Database %sis out-of-date. Deleting...\n", lpDatabaseName)); if (!DeleteFile(lpDatabaseName)) { DWORD err = GetLastError(); RemoveDirectory(lpDatabaseName); } LPWSTR lpPath = GetPath(lpDatabaseName); if (lpPath) { wchar_t *pTemp = new wchar_t [wcslen(lpDatabaseName) + 50]; CDeleteMe d2 (pTemp); if (pTemp) { swprintf(pTemp, L"%sedb.log", lpPath); if (!DeleteFile(pTemp)) RemoveDirectory(pTemp); swprintf(pTemp, L"%sedb.chk", lpPath); if (!DeleteFile(pTemp)) RemoveDirectory(pTemp); swprintf(pTemp, L"%sres1.log", lpPath); if (!DeleteFile(pTemp)) RemoveDirectory(pTemp); swprintf(pTemp, L"%sres2.log", lpPath); if (!DeleteFile(pTemp)) RemoveDirectory(pTemp); swprintf(pTemp, L"%stmp.edb", lpPath); if (!DeleteFile(pTemp)) RemoveDirectory(pTemp); swprintf(pTemp, L"%s*.log", lpPath); _bstr_ts names; WIN32_FIND_DATA fd; HANDLE hFile = FindFirstFile(pTemp, &fd); while (TRUE) { if (wcscmp(fd.cFileName, L".") && wcscmp(fd.cFileName, L"..")) { swprintf(pTemp, L"%s%s", lpPath, fd.cFileName); names.push_back(pTemp); } if (!FindNextFile(hFile, &fd)) break; } for (int i = 0; i < names.size(); i++) { if (!DeleteFile(names.at(i))) RemoveDirectory(names.at(i)); } } else hr = WBEM_E_OUT_OF_MEMORY; } else hr = WBEM_E_FAILED; return hr; } BOOL CheckVersion (JET_SESID sesid, JET_DBID dbid, int iVersion) { BOOL bDelete = FALSE; JET_ERR err; JET_TABLEID tableid; JET_COLUMNID id; DWORD dwCurrVer = 0; err = JetOpenTable (sesid, dbid, "DBVersion", NULL, 0, JET_bitTableUpdatable, &tableid); if (err >= JET_errSuccess) { JET_COLUMNDEF columnDef; err = JetGetColumnInfo(sesid, dbid, "DBVersion", "Version", &columnDef, sizeof(JET_COLUMNDEF), 0); if (err < JET_errSuccess) { columnDef.cp = 1200; // Unicode? Otherwise, its 1252. columnDef.wCountry = 1; columnDef.langid = 1033; columnDef.wCollate = 0; columnDef.cbStruct = sizeof(JET_COLUMNDEF); columnDef.columnid = 1; columnDef.coltyp = JET_coltypLong; columnDef.grbit = 0 ; columnDef.cbMax = 0; err = JetAddColumn(sesid, tableid, "Version", &columnDef, "", 0, &id); } else id = columnDef.columnid; ULONG lLen; err = JetMove(sesid, tableid, JET_MoveFirst, 0); err = JetRetrieveColumn(sesid, tableid, id, &dwCurrVer, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess == err && lLen != 0) { if (iVersion != dwCurrVer) bDelete = TRUE; } JetCloseTable(sesid, tableid); } else { // Do any other tables exist? err = JetOpenTable(sesid, dbid, "ClassMap", NULL, 0, JET_bitTableUpdatable, &tableid); if (err == JET_errSuccess) { bDelete = TRUE; JetCloseTable(sesid, tableid); } } return bDelete; } //*************************************************************************** // // AttachESEDatabase // //*************************************************************************** HRESULT AttachESEDatabase(DBPROPSET *pTemplate, CSQLConnection *pConn, BOOL bCheckVer = FALSE) { HRESULT hr = WBEM_S_NO_ERROR; CESEConnection *pConn2 = (CESEConnection *)pConn; JET_SESID sesid = pConn2->GetSessionID(); JET_ERR err = JET_errSuccess; JET_DBID dbid; CLASSMAP cm; char *pDB = GetAnsiString(pTemplate->rgProperties[4].vValue.bstrVal); if (!pDB) hr = WBEM_E_OUT_OF_MEMORY; IWbemClassObject *pTest = NULL; CDeleteMe d (pDB); if (SUCCEEDED(hr)) { LPWSTR lpDatabase = pTemplate->rgProperties[4].vValue.bstrVal; err = JetAttachDatabase( sesid, pDB, 0 ) ; if (err < JET_errSuccess) { if (err == JET_errDatabaseCorrupted) { // DeleteDatabase(lpDatabase); hr = CSQLExecute::GetWMIError(err); return hr; } err = JetCreateDatabase(sesid, pDB, NULL, &dbid, 0); if (err == JET_errSuccess) { pConn2->SetDBID(dbid); } else { hr = CSQLExecute::GetWMIError(err); return hr; } } else { err = JetOpenDatabase (sesid, pDB, NULL, &dbid, 0); if (err == JET_errSuccess) { if (bCheckVer) { BOOL bDelete = CheckVersion(sesid, dbid, CURRENT_DB_VERSION); // Ensure that this database is the proper version JET_TABLEID tableid; err = JetOpenTable (sesid, dbid, "ClassMap", NULL, 0, JET_bitTableUpdatable, &tableid); if (err == JET_errSuccess) { JET_COLUMNDEF columnDef; // If the table exists but the column doesn't, this is // an old beta version, and we need to delete it and // start over. err = JetGetColumnInfo(sesid, dbid, "ClassMap", "ClassBlob", &columnDef, sizeof(JET_COLUMNDEF), 0); if (err != JET_errSuccess) bDelete = TRUE; JetCloseTable(sesid, tableid); } if (bDelete) { err = JetCloseDatabase(sesid, dbid, 0); err = JetEndSession(sesid, 0); err = JetTerm2(gJetInst, JET_bitTermComplete); hr = DeleteDatabase(lpDatabase); return WBEM_E_DATABASE_VER_MISMATCH; } } pConn2->SetDBID(dbid); } else { hr = CSQLExecute::GetWMIError(err); return hr; } } // Initialize our data. DWORD dwPos; LPWSTR lpTableName = NULL; // Create the tables. err = JetBeginTransaction(sesid); if (FAILED(hr = UpdateDBVersion(pConn, CURRENT_DB_VERSION)) || FAILED(hr = SetupObjectMapAccessor(pConn)) || FAILED(hr = SetupClassMapAccessor(pConn)) || FAILED(hr = SetupPropertyMapAccessor(pConn)) || FAILED(hr = SetupClassDataAccessor(pConn)) || FAILED(hr = SetupIndexDataAccessor(pConn, WMIDB_STORAGE_STRING, dwPos, &lpTableName))|| FAILED(hr = SetupClassKeysAccessor(pConn))) goto Exit; CDeleteMe dmlpTableName( lpTableName ); hr = GetFirst_ClassMap(pConn, 1, cm); if (SUCCEEDED(hr)) { cm.Clear(); goto Exit; } // Default system classes. if (FAILED(hr = InsertObjectMap(pConn, 1, L"meta_class", 3, L"meta_class", 0, 0, 0, 0, TRUE)) || FAILED(hr = InsertObjectMap(pConn, 2372429868687864876, L"__Namespace", 3, L"__Namespace", 0, 0, 0, 1, TRUE)) || FAILED(hr = InsertObjectMap(pConn, -1411745643584611171, L"root", 3, L"root", 0, 0, 0, 2372429868687864876, TRUE)) || FAILED(hr = InsertObjectMap(pConn, 3373910491091605771, L"__Instances", 3, L"__Instances", 0, 0, 0, 1, TRUE)) || FAILED(hr = InsertScopeMap_Internal(pConn, -1411745643584611171, L"root", 0)) || FAILED(hr = InsertObjectMap(pConn, -7316356768687527881, L"__Container_Association", 3, L"__Container_Association", 0, 0, 0, 1, TRUE)) || FAILED(hr = InsertClassMap(pConn, 1, L"meta_class", 0, 1, NULL, 0, TRUE))) goto Exit; // Repository-specific system classes if (FAILED(GetFirst_ClassMap(pConn, 2372429868687864876, cm))) { _IWmiObject *pObj = NULL; hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER, IID__IWmiObject, (void **)&pObj); CReleaseMe r (pObj); if (SUCCEEDED(hr)) { VARIANT vTemp; VariantInit(&vTemp); vTemp.bstrVal = SysAllocString(L"__Namespace"); vTemp.vt = VT_BSTR; pObj->Put(L"__Class", 0, &vTemp, CIM_STRING); VariantClear(&vTemp); pObj->Put(L"Name", 0, NULL, CIM_STRING); IWbemQualifierSet *pQS = NULL; hr = pObj->GetPropertyQualifierSet(L"Name", &pQS); if (SUCCEEDED(hr)) { vTemp.boolVal = 1; vTemp.vt = VT_BOOL; pQS->Put(L"key", &vTemp, 0); pQS->Release(); VariantClear(&vTemp); } BYTE buff[128]; DWORD dwLen = 0; hr = pObj->Unmerge(0, 128, &dwLen, &buff); if (dwLen > 0) { BYTE *pBuff = new BYTE [dwLen]; if (pBuff) { CDeleteMe r2 (pBuff); DWORD dwLen1; hr = pObj->Unmerge(0, dwLen, &dwLen1, pBuff); if (SUCCEEDED(hr)) { hr = InsertClassMap(pConn, 2372429868687864876, L"__Namespace", 1, 2372429868687864876, pBuff, dwLen, TRUE); } } else hr = WBEM_E_OUT_OF_MEMORY; } } if (FAILED(hr)) goto Exit; } cm.Clear(); if (FAILED(GetFirst_ClassMap(pConn, 3373910491091605771, cm))) { _IWmiObject *pObj = NULL; hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER, IID__IWmiObject, (void **)&pObj); CReleaseMe r (pObj); if (SUCCEEDED(hr)) { VARIANT vTemp; VariantInit(&vTemp); vTemp.bstrVal = SysAllocString(L"__Instances"); vTemp.vt = VT_BSTR; pObj->Put(L"__Class", 0, &vTemp, CIM_STRING); VariantClear(&vTemp); pObj->Put(L"ClassName", 0, NULL, CIM_STRING); IWbemQualifierSet *pQS = NULL; hr = pObj->GetPropertyQualifierSet(L"ClassName", &pQS); if (SUCCEEDED(hr)) { vTemp.boolVal = 1; vTemp.vt = VT_BOOL; pQS->Put(L"key", &vTemp, 0); pQS->Release(); VariantClear(&vTemp); } BYTE buff[128]; DWORD dwLen = 0; hr = pObj->Unmerge(0, 128, &dwLen, &buff); if (dwLen > 0) { BYTE *pBuff = new BYTE [dwLen]; if (pBuff) { CDeleteMe r2 (pBuff); DWORD dwLen1; hr = pObj->Unmerge(0, dwLen, &dwLen1, pBuff); if (SUCCEEDED(hr)) { hr = InsertClassMap(pConn, 3373910491091605771, L"__Instances", 1, 3373910491091605771, pBuff, dwLen, TRUE); } } else hr = WBEM_E_OUT_OF_MEMORY; } } if (FAILED(hr)) goto Exit; } cm.Clear(); if (FAILED(GetFirst_ClassMap(pConn, -7316356768687527881, cm))) { _IWmiObject *pObj = NULL; hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER, IID__IWmiObject, (void **)&pObj); CReleaseMe r (pObj); if (SUCCEEDED(hr)) { VARIANT vTemp; VariantInit(&vTemp); vTemp.bstrVal = SysAllocString(L"__Container_Association"); vTemp.vt = VT_BSTR; pObj->Put(L"__Class", 0, &vTemp, CIM_STRING); VariantClear(&vTemp); pObj->Put(L"Containee", 0, NULL, CIM_REFERENCE); pObj->Put(L"Container", 0, NULL, CIM_REFERENCE); IWbemQualifierSet *pQS = NULL; hr = pObj->GetPropertyQualifierSet(L"Containee", &pQS); if (SUCCEEDED(hr)) { vTemp.boolVal = 1; vTemp.vt = VT_BOOL; pQS->Put(L"key", &vTemp, 0); pQS->Release(); VariantClear(&vTemp); } hr = pObj->GetPropertyQualifierSet(L"Container", &pQS); if (SUCCEEDED(hr)) { vTemp.boolVal = 1; vTemp.vt = VT_BOOL; pQS->Put(L"key", &vTemp, 0); pQS->Release(); VariantClear(&vTemp); } BYTE buff[128]; DWORD dwLen = 0; hr = pObj->Unmerge(0, 128, &dwLen, &buff); if (dwLen > 0) { BYTE *pBuff; pBuff = new BYTE [dwLen]; if (pBuff) { CDeleteMe r2 (pBuff); DWORD dwLen1; hr = pObj->Unmerge(0, dwLen, &dwLen1, pBuff); if (SUCCEEDED(hr)) { hr = InsertClassMap(pConn, -7316356768687527881, L"__Container_Association", 1, -7316356768687527881, pBuff, dwLen, TRUE); } } else hr = WBEM_E_OUT_OF_MEMORY; } } if (FAILED(hr)) goto Exit; } cm.Clear(); // Properties for default classes DWORD iWaste = 0, dwPropID = 0; if (FAILED(hr = InsertPropertyMap(pConn, dwPropID, 2372429868687864876, 1, 8, L"Name", 4, TRUE)) || FAILED(hr = InsertClassKeys(pConn, 2372429868687864876, dwPropID)) || FAILED(hr = InsertPropertyMap(pConn, iWaste, 3373910491091605771, 1, 8, L"ClassName", 4, TRUE)) || FAILED(hr = InsertClassKeys(pConn, 3373910491091605771, iWaste)) || FAILED(hr = InsertPropertyMap(pConn, iWaste, -7316356768687527881, 4, 102, L"Containee", 4, TRUE)) || FAILED(hr = InsertClassKeys(pConn, -7316356768687527881, iWaste)) || FAILED(hr = InsertPropertyMap(pConn, iWaste, -7316356768687527881, 4, 102, L"Container", 4, TRUE)) || FAILED(hr = InsertClassKeys(pConn, -7316356768687527881, iWaste)) || FAILED(hr = InsertClassData_Internal(pConn, -1411745643584611171, dwPropID, 0, 0, 2372429868687864876, L"root", 0, 0, 4, 0, 0, FALSE)) || FAILED(hr = InsertIndexData (pConn, -1411745643584611171, dwPropID, 0, L"root", 0, 0, 1))) goto Exit; // System properties. Including them in the schema makes them queriable. hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER, IID_IWbemClassObject, (void **)&pTest); if (SUCCEEDED(hr)) { CReleaseMe r (pTest); BSTR strName; CIMTYPE cimtype; hr = pTest->BeginEnumeration(0); while (pTest->Next(0, &strName, NULL, &cimtype, NULL) == S_OK) { DWORD dwStorageType = 0; CFreeMe f1 (strName); DWORD dwFlags = REPDRVR_FLAG_SYSTEM; CIMTYPE ct = cimtype & 0xFFF; bool bArray = (cimtype & CIM_FLAG_ARRAY)? true: false; if (bArray) dwFlags |= REPDRVR_FLAG_ARRAY; if (!_wcsicmp(strName, L"__Path") || !_wcsicmp(strName, L"__RelPath") || !_wcsicmp(strName, L"__Class") || !_wcsicmp(strName, L"__SuperClass") || !_wcsicmp(strName, L"__Dynasty") || !_wcsicmp(strName, L"__Derivation") || !_wcsicmp(strName, L"__Version") || !_wcsicmp(strName, L"__Genus") || !_wcsicmp(strName, L"__Property_Count") || !_wcsicmp(strName, L"__Server") || !_wcsicmp(strName, L"__Namespace")) dwStorageType = WMIDB_STORAGE_COMPACT; else dwStorageType = GetStorageType(ct, bArray); if (FAILED(hr = InsertPropertyMap(pConn, iWaste, 1, dwStorageType, ct, strName, dwFlags, TRUE))) goto Exit; } } hr = WBEM_S_NO_ERROR; } Exit: if (SUCCEEDED(hr)) { hr = CSQLExecute::GetWMIError(err); JetCommitTransaction(sesid, 0); } else JetRollback(sesid, 0); return hr; } //*************************************************************************** // // CSQLConnCache::FinalRollback // //*************************************************************************** HRESULT CSQLConnCache::FinalRollback(CSQLConnection *pConn) { HRESULT hr = WBEM_S_NO_ERROR; // Rollback this transaction and set Thread ID to zero CESEConnection *pConn2 = (CESEConnection *)pConn; CWmiESETransaction *pTrans = pConn2->m_pTrans; if (pTrans) { hr = pTrans->Abort(); delete pTrans; } pConn2->m_pTrans = NULL; pConn2->m_bInUse = false; pConn2->m_tCreateTime = time(0); // We don't want to delete it immediately. return hr; } //*************************************************************************** // // CSQLConnCache::FinalCommit // //*************************************************************************** HRESULT CSQLConnCache::FinalCommit(CSQLConnection *pConn) { HRESULT hr = WBEM_S_NO_ERROR; // Commit this transaction and erase the ThreadID // from this connection. CESEConnection *pConn2 = (CESEConnection *)pConn; CWmiESETransaction *pTrans = pConn2->m_pTrans; if (pTrans) hr = pTrans->Commit(); pConn2->m_tCreateTime = time(0); // We don't want to delete it immediately. delete pTrans; pConn2->m_pTrans = NULL; return hr; } //*************************************************************************** // // CSQLConnCache::ReleaseConnection // //*************************************************************************** HRESULT CSQLConnCache::ReleaseConnection(CSQLConnection *_pConn, HRESULT retcode, BOOL bDistributed) { HRESULT hr = WBEM_S_NO_ERROR; DWORD dwNumFreed = 0; // If we're shutting down, the connection will be released anyway. if (m_dwStatus == WBEM_E_SHUTTING_DOWN) { hr = FinalRollback(_pConn); ((CESEConnection *)_pConn)->m_bInUse = false; return WBEM_E_SHUTTING_DOWN; } CRepdrvrCritSec r (&m_cs); for (int i = m_Conns.size() -1; i >=0; i--) { CSQLConnection *pConn = m_Conns.at(i); if (pConn) { CESEConnection *pConn2 = (CESEConnection *)pConn; if (_pConn == pConn) { if (FAILED(retcode)) { // If this is a distributed transaction, // they decide on the final commit. if (!bDistributed) { hr = FinalRollback(pConn); if (retcode == WBEM_E_CRITICAL_ERROR || retcode == WBEM_E_INVALID_QUERY || retcode == WBEM_E_OUT_OF_MEMORY) { delete pConn2; // This deletes the transaction. pConn2 = NULL; m_Conns.erase(&m_Conns.at(i)); DEBUGTRACE((LOG_WBEMCORE, "THREAD %ld deleted ESE connection %X. Number of connections = %ld\n", GetCurrentThreadId(), pConn, m_Conns.size())); } } } else { // If this is a distributed transaction, // they decide on the final commit. if (!bDistributed) hr = FinalCommit(pConn); } if (pConn2) pConn2->m_bInUse = false; dwNumFreed++; break; } } } // Notify waiting threads that there is // an open connection. // ===================================== { CRepdrvrCritSec r (&m_cs); for (int i = 0; i < m_WaitQueue.size(); i++) { if (i >= dwNumFreed) break; HANDLE hTemp = m_WaitQueue.at(i); SetEvent(hTemp); DEBUGTRACE((LOG_WBEMCORE, "Thread %ld released a connection...\n", GetCurrentThreadId())); } } return hr; } //*************************************************************************** // // CSQLConnCache::Shutdown // //*************************************************************************** HRESULT CSQLConnCache::Shutdown() { HRESULT hr = WBEM_S_NO_ERROR; JET_ERR err = 0; time_t tStart = time(0), tEnd = time(0) + 5; m_dwStatus = WBEM_E_SHUTTING_DOWN; if (m_bInit) { CRepdrvrCritSec r (&m_cs); int iConnectionsLeftOpen = m_Conns.size(); while (iConnectionsLeftOpen) { { CRepdrvrCritSec r (&m_cs); iConnectionsLeftOpen = 0; for (int i = m_Conns.size()-1; i >= 0; i--) { // Give threads up to 5 seconds to shut down. if (((CESEConnection *)m_Conns.at(i))->m_bInUse) iConnectionsLeftOpen++; else if (!((CESEConnection *)m_Conns.at(i))->m_bInUse) { delete m_Conns.at(i); m_Conns.erase(&m_Conns.at(i)); } } } if (!iConnectionsLeftOpen) break; else { if (tEnd >= tStart) { Sleep(100); // Check every 50 ms. tStart = time(0); } else break; } } if (iConnectionsLeftOpen) { CRepdrvrCritSec r (&m_cs); for (int i = m_Conns.size()-1; i >= 0; i--) { // Give threads up to 5 seconds to shut down. if (((CESEConnection *)m_Conns.at(i))->m_bInUse) { CESEConnection *pConn2 = (CESEConnection *)m_Conns.at(i); if (pConn2) { DEBUGTRACE((LOG_WBEMCORE, "CONNECTION: #%ld \n" " In Use = %ld\n" " Creation time = %ld\n" " Thread ID = %ld\n", i, ((CESEConnection *)pConn2)->m_bInUse, ((CESEConnection *)pConn2)->m_tCreateTime, ((CESEConnection *)pConn2)->m_dwThreadId)); } } } m_Conns.clear(); } DEBUGTRACE((LOG_WBEMCORE, "Database shutting down in response to a Shutdown command.\n")); if (iConnectionsLeftOpen) ERRORTRACE((LOG_WBEMCORE, "%ld connections left open. All threads did not release their connections!\n", iConnectionsLeftOpen)); // _ASSERT(iConnectionsLeftOpen == 0, "Shutdown was unable to close all db connections."); err = JetTerm2(gJetInst, JET_bitTermComplete); if (err >= JET_errSuccess) { gJetInst = NULL; m_bInit = FALSE; } hr = CSQLExecute::GetWMIError(err); } return hr; } //*************************************************************************** // // Startup // //*************************************************************************** HRESULT Startup(CSQLConnection *pConn) { HRESULT hr = WBEM_S_NO_ERROR; hr = CleanAutoDeletes(pConn); return hr; } //*************************************************************************** // // CSQLConnCache::DeleteUnusedConnections // //*************************************************************************** HRESULT CSQLConnCache::DeleteUnusedConnections(BOOL bDeadOnly) { HRESULT hr = WBEM_E_NOT_FOUND; DWORD dwThreadId = GetCurrentThreadId(); CRepdrvrCritSec r (&m_cs); for (int i = m_Conns.size()-1; i >= 0; i--) { CESEConnection *pConn = (CESEConnection *)m_Conns.at(i); if (pConn) { if (!pConn->m_bInUse) { BOOL bDelete = FALSE; if (bDeadOnly) { if (dwThreadId != pConn->m_dwThreadId) { HANDLE hTemp = OpenThread(STANDARD_RIGHTS_REQUIRED, FALSE, pConn->m_dwThreadId); if (hTemp) { CloseHandle(hTemp); time_t tNow = time(0); if ((tNow - pConn->m_tCreateTime) > 60) bDelete = TRUE; } else bDelete = TRUE; } } else bDelete = TRUE; if (bDelete) { delete pConn; // This deletes the transaction, which should be NULL. pConn = NULL; m_Conns.erase(&m_Conns.at(i)); hr = WBEM_S_NO_ERROR; if (!bDeadOnly) break; } } } } return hr; } //*************************************************************************** // // CSQLConnCache::GetConnection // //*************************************************************************** HRESULT CSQLConnCache::GetConnection(CSQLConnection **ppConn, BOOL bTransacted, BOOL bDistributed, DWORD dwTimeOutSecs) { HRESULT hr = WBEM_S_NO_ERROR; bool bFound = false; JET_ERR err = 0; BOOL bStartUp = FALSE; DWORD dwThreadId = GetCurrentThreadId(); if (!ppConn) return WBEM_E_INVALID_PARAMETER; if (m_dwStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN; if (m_WaitQueue.size() && dwTimeOutSecs > 0) goto Queue; // Look for any connection that belongs // to a thread that has gone bye-bye // and kill it. // =================================== { CRepdrvrCritSec r (&m_cs); DeleteUnusedConnections(TRUE); // See if there are any free connections. // ====================================== if (m_Conns.size() > 0) { for (int i = 0; i < m_Conns.size(); i++) { CESEConnection *pConn = (CESEConnection *)m_Conns.at(i); if (pConn) { time_t tTemp = time(0); if (!pConn->m_bInUse) { // We need // to reuse the same connection, // since Jet is apartment-model // ============================ if (dwThreadId == pConn->m_dwThreadId) { pConn->m_bInUse = true; pConn->m_tCreateTime = time(0); *ppConn = pConn; bFound = true; break; } } } } } // If there were no free connections, try and obtain a new one. // ============================================================ { if (!bFound && (m_Conns.size() < m_dwMaxNumConns)) { if (!m_bInit) { // Get a new JET_INSTANCE from the parameters // in m_pPropSet // m_sDatabaseName = database name // m_pPropSet[1].bstrVal = user name // m_pPropSet[2].bstrVal = password LPWSTR lpPath = GetPath(m_sDatabaseName); if (lpPath) { CDeleteMe d (lpPath); char * pPath2 = GetAnsiString(lpPath); if (!pPath2) return WBEM_E_OUT_OF_MEMORY; CDeleteMe d3 (pPath2); if (pPath2) { DWORD dwVal = 1024; if ((err = JetSetSystemParameter (&gJetInst, 0, JET_paramMaxSessions, 25, NULL)) != JET_errSuccess || (err = JetSetSystemParameter (&gJetInst, 0, JET_paramCacheSizeMin, 100, NULL)) != JET_errSuccess || (err = JetSetSystemParameter (&gJetInst, 0, JET_paramCacheSizeMax, 1024, NULL)) != JET_errSuccess || (err = JetSetSystemParameter (&gJetInst, 0, JET_paramEventLogCache, 65536, NULL)) != JET_errSuccess || (err = JetSetSystemParameter (&gJetInst, 0, JET_paramCircularLog, TRUE, NULL)) != JET_errSuccess || (err = JetSetSystemParameter( &gJetInst, 0, JET_paramSystemPath, 0, pPath2)) != JET_errSuccess || (err = JetSetSystemParameter( &gJetInst, 0, JET_paramTempPath, 0, pPath2)) != JET_errSuccess || (err = JetSetSystemParameter( &gJetInst, 0, JET_paramLogFilePath, 0, pPath2)) != JET_errSuccess || (err = JetSetSystemParameter( &gJetInst, 0, JET_paramMaxVerPages, dwVal, NULL)) != JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); } else { err = JetInit(&gJetInst); //if (err < JET_errSuccess) // { // hr = DeleteDatabase(m_sDatabaseName); // if (SUCCEEDED(hr)) // err = JetInit(&gJetInst); // } if (err == JET_errSuccess) { m_bInit = TRUE; bStartUp = TRUE; } else hr = CSQLExecute::GetWMIError(err); } } } else hr = WBEM_E_INVALID_PARAMETER; } // If that worked, get a new session, // and attach the current DB. if (SUCCEEDED(hr)) { char *pUser = GetAnsiString(m_pPropSet->rgProperties[2].vValue.bstrVal); char *pPwd = GetAnsiString(m_pPropSet->rgProperties[3].vValue.bstrVal); CDeleteMe d3 (pUser), d4 (pPwd); if (!pUser || !pPwd) return WBEM_E_OUT_OF_MEMORY; JET_SESID session; err = JetBeginSession(gJetInst, &session, pUser, pPwd); if (err == JET_errSuccess) { CSQLConnection *pConn = (CSQLConnection *)new CESEConnection(session); if (pConn) { hr = AttachESEDatabase(m_pPropSet, pConn, bStartUp); if (FAILED(hr) && hr == WBEM_E_DATABASE_VER_MISMATCH) { if ((JetInit(&gJetInst) != JET_errSuccess) || (JetBeginSession(gJetInst, &session, pUser, pPwd) != JET_errSuccess) || !((CESEConnection *)pConn)->SetSessionID(session) || (FAILED(hr = AttachESEDatabase(m_pPropSet, pConn, bStartUp)))) hr = WBEM_E_DATABASE_VER_MISMATCH; } if (SUCCEEDED(hr) && bStartUp) hr = Startup(pConn); if (SUCCEEDED(hr)) { ((CESEConnection *)pConn)->m_bInUse = true; ((CESEConnection *)pConn)->m_tCreateTime = time(0); ((CESEConnection *)pConn)->m_dwThreadId = dwThreadId; m_Conns.push_back(pConn); DEBUGTRACE((LOG_WBEMCORE, "THREAD %ld obtained new ESE connection %X, session %X. Number of connections = %ld\n", dwThreadId, pConn, &session, m_Conns.size())); #ifdef _DEBUG_CONNS for (int i = 0; i < m_Conns.size()-1; i++) { CESEConnection *pConn2 = (CESEConnection *)m_Conns.at(i); if (pConn) { DEBUGTRACE((LOG_WBEMCORE, "CONNECTION: #%ld \n" " In Use = %ld\n" " Creation time = %ld\n" " Thread ID = %ld\n", i, ((CESEConnection *)pConn2)->m_bInUse, ((CESEConnection *)pConn2)->m_tCreateTime, ((CESEConnection *)pConn2)->m_dwThreadId)); } } #endif *ppConn = pConn; } else delete pConn; } else hr = WBEM_E_OUT_OF_MEMORY; } else { int iNumConns = m_Conns.size(); hr = CSQLExecute::GetWMIError(err); } } } } if (SUCCEEDED(hr) && *ppConn != NULL && (bTransacted || bDistributed)) { CESEConnection *pConn = (CESEConnection *)*ppConn; CWmiESETransaction *pTrans = pConn->GetTransaction(); if (!pTrans) { pTrans = new CWmiESETransaction(((CESEConnection *)pConn)->GetSessionID()); pConn->SetTransaction(pTrans); } if (pTrans) pTrans->StartTransaction(); } } Queue: // Otherwise, wait for a connection to be released. // ================================================ if (!*ppConn && (m_Conns.size() >= m_dwMaxNumConns || m_WaitQueue.size()) && dwTimeOutSecs > 0) { DEBUGTRACE((LOG_WBEMCORE, "WARNING: >> Number of ESE connections exceeded (%ld). Thread %ld is waiting on one to be released...\n", m_Conns.size(), dwThreadId)); BOOL bWait = FALSE; HANDLE hThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hThreadEvent != INVALID_HANDLE_VALUE) { CRepdrvrCritSec r (&m_cs); // Reserve our spot in the queue so we get the very next connection. m_WaitQueue.push_back(hThreadEvent); // Check for a free connection one last time. hr = DeleteUnusedConnections(FALSE); if (SUCCEEDED(hr)) hr = GetConnection(ppConn, bTransacted, bDistributed, 0); else bWait = TRUE; } else hr = WBEM_E_OUT_OF_MEMORY; if (bWait) { if (WbemWaitForSingleObject(hThreadEvent, 30*1000) == WAIT_OBJECT_0) { hr = GetConnection(ppConn, bTransacted, bDistributed, 0); if (SUCCEEDED(hr)) DEBUGTRACE((LOG_WBEMCORE, "Thread %ld obtained a connection.\n", dwThreadId)); else DEBUGTRACE((LOG_WBEMCORE, "Thread %ld failed to obtain a connection.\n", dwThreadId)); } else hr = WBEM_E_SERVER_TOO_BUSY; } // Remove ourself from the queue // This will happen whether the GetConnection // succeeded or failed // ========================================== { CRepdrvrCritSec r (&m_cs); for (int i = 0; i < m_WaitQueue.size(); i++) { if (hThreadEvent == m_WaitQueue.at(i)) { m_WaitQueue.erase(&m_WaitQueue.at(i)); break; } } CloseHandle(hThreadEvent); } CloseHandle(hThreadEvent); } if (!*ppConn && SUCCEEDED(hr)) { DEBUGTRACE((LOG_WBEMCORE, "Thread %ld was unable to obtain a connection.\n", dwThreadId)); hr = WBEM_E_SERVER_TOO_BUSY; } return hr; } //*************************************************************************** // // CSQLExecute::GetWMIError // //*************************************************************************** HRESULT CSQLExecute::GetWMIError(long ErrorID) { HRESULT hr = 0; switch(ErrorID) { case JET_errSuccess: case JET_errRecordDeleted: hr = WBEM_S_NO_ERROR; break; case JET_wrnNyi: hr = E_NOTIMPL; break; case JET_errOutOfMemory: case JET_errOutOfDatabaseSpace: case JET_errOutOfCursors: case JET_errOutOfBuffers: case JET_errOutOfFileHandles: case JET_errVersionStoreOutOfMemory: case JET_errCurrencyStackOutOfMemory: hr = WBEM_E_OUT_OF_MEMORY; break; case JET_errInvalidParameter: case JET_errKeyTooBig: case JET_errInvalidGrbit: case JET_errInvalidName: hr = WBEM_E_INVALID_PARAMETER; break; case JET_errRecordNotDeleted: case JET_errWriteConflict: hr = WBEM_E_FAILED; break; case JET_errRecordNotFound: case JET_errDatabaseNotFound: case JET_errNoCurrentRecord: case JET_errFileNotFound: hr = WBEM_E_NOT_FOUND; break; case JET_errNTSystemCallFailed: case JET_errLogFileCorrupt: case JET_errDatabaseInconsistent: case JET_errConsistentTimeMismatch: case JET_errDatabasePatchFileMismatch: case JET_errInvalidDatabaseId: case JET_errDiskIO: case JET_errInvalidPath: case JET_errInvalidSystemPath: case JET_errInvalidLogDirectory: case JET_errInvalidDatabase: case JET_errInvalidFilename: case JET_errPageSizeMismatch: hr = WBEM_E_CRITICAL_ERROR; break; case JET_errFileAccessDenied: case JET_errPermissionDenied: hr = WBEM_E_ACCESS_DENIED; break; case JET_errOutOfSessions: case JET_errInvalidSesid: hr = WBEM_E_CONNECTION_FAILED; break; case JET_errQueryNotSupported: case JET_errSQLLinkNotSupported: hr = WBEM_E_INVALID_QUERY; break; default: if (ErrorID > 0) hr = WBEM_S_NO_ERROR; else hr = WBEM_E_INVALID_QUERY; } if (FAILED(hr) && hr != WBEM_E_NOT_FOUND) ERRORTRACE((LOG_WBEMCORE, "Jet returned the following error: %ld\n", ErrorID)); return hr; } HRESULT SetInArray (VARIANT &vOriginal, DWORD iPos, VARIANT &vNew, CIMTYPE ct) { HRESULT hr = 0; if (vOriginal.vt & CIM_FLAG_ARRAY) { SAFEARRAY *pArray = V_ARRAY(&vOriginal); SAFEARRAYBOUND aBounds[1]; long lLBound, lUBound; DWORD Comp = (DWORD)iPos+1; SafeArrayGetLBound(pArray, 1, &lLBound); SafeArrayGetUBound(pArray, 1, &lUBound); lUBound -= lLBound; lUBound += 1; if (Comp > lUBound) { aBounds[0].cElements = Comp; aBounds[0].lLbound = 0; SAFEARRAY *pNew = SafeArrayCreate(vNew.vt, 1, aBounds); if (pNew) { for ( int i = 0; i < lUBound; i++ ) { long lTemp[1]; lTemp[0] = i; if ( (ct & 0xFFF) == CIM_STRING || (ct & 0xFFF) == CIM_DATETIME || (ct & 0xFFF) == CIM_REFERENCE ) { BSTR bstr; if ( SUCCEEDED(SafeArrayGetElement( pArray, lTemp, &bstr) ) ) { SafeArrayPutElement( pNew, lTemp, bstr ); SysFreeString( bstr ); } } else if ( (ct & 0xFFF) == CIM_OBJECT ) { IUnknown* pObj; if ( SUCCEEDED(SafeArrayGetElement( pArray, lTemp, &pObj) ) ) { SafeArrayPutElement( pNew, lTemp, pObj ); pObj->Release(); } } else { double dbVal; if ( SUCCEEDED(SafeArrayGetElement( pArray, lTemp, &dbVal ) ) ) { SafeArrayPutElement( pNew, lTemp, &dbVal ); } } } SafeArrayDestroy(pArray); pArray = pNew; } } hr = PutVariantInArray(&pArray, iPos, &vNew); if (SUCCEEDED(hr)) V_ARRAY(&vOriginal) = pArray; } else { VariantClear(&vOriginal); // This is a new object. SAFEARRAYBOUND aBounds[1]; aBounds[0].cElements = iPos+1; aBounds[0].lLbound = 0; SAFEARRAY* pArray = SafeArrayCreate(vNew.vt, 1, aBounds); if (pArray) { hr = PutVariantInArray(&pArray, iPos, &vNew); vOriginal.vt = VT_ARRAY|vNew.vt; V_ARRAY(&vOriginal) = pArray; } else hr = WBEM_E_OUT_OF_MEMORY; } return hr; } //*************************************************************************** // // SetObjectData // //*************************************************************************** HRESULT SetObjectData(CSQLConnection *pConn, IWbemClassObject *pNewObj, IWmiDbSession *pSession, CSchemaCache *pSchema, CLASSDATA cd, BOOL bBlobData, BOOL &bBigText, BOOL *bObject=NULL, BOOL bNoDefaults=FALSE) { HRESULT hr = 0; _bstr_t sPropName; DWORD dwStorage, dwCIMType, dwPropFlags; VARIANT vValue; VariantInit(&vValue); vValue.vt = VT_NULL; wchar_t wTemp[455]; BOOL bSkip = FALSE; int iLen = 0; SQL_ID dRefId, dClassId; if (bObject) *bObject = FALSE; dRefId = cd.dRefId; hr = pSchema->GetPropertyInfo (cd.iPropertyId, &sPropName, NULL, &dwStorage, &dwCIMType, &dwPropFlags); if (SUCCEEDED(hr)) { if (bNoDefaults && !(dwPropFlags & REPDRVR_FLAG_NONPROP)) return WBEM_S_NO_ERROR; if (!(cd.iFlags & ESE_FLAG_NULL)) { switch(dwStorage) { case WMIDB_STORAGE_REFERENCE: // Reference or object case WMIDB_STORAGE_STRING: if (bBlobData) { if ((dwCIMType == CIM_STRING || dwCIMType == CIM_REFERENCE) && cd.dwBufferLen > 0) { vValue.vt = VT_BSTR; vValue.bstrVal = SysAllocString((LPWSTR)cd.pBuffer); if (vValue.bstrVal) iLen = wcslen(vValue.bstrVal); } else { vValue.vt = VT_NULL; iLen = 0; } } else { if (cd.sPropertyStringValue != NULL) { vValue.bstrVal = SysAllocString(cd.sPropertyStringValue); if (vValue.bstrVal) { vValue.vt = VT_BSTR; iLen = wcslen(vValue.bstrVal); bBigText = IsTruncated(vValue.bstrVal, 127); } } } break; case WMIDB_STORAGE_NUMERIC: // Set in one of the kajillion numeric types... if (dwCIMType == CIM_UINT64 || dwCIMType == CIM_SINT64) { wchar_t wTemp[50]; swprintf(wTemp, L"%I64d", cd.dPropertyNumericValue); vValue.bstrVal = SysAllocString(wTemp); vValue.vt = VT_BSTR; } else if (dwCIMType == CIM_BOOLEAN) { vValue.boolVal = (BOOL) cd.dPropertyNumericValue; vValue.vt = VT_BOOL; } else { vValue.lVal = (DWORD) cd.dPropertyNumericValue; vValue.vt = VT_I4; } break; case WMIDB_STORAGE_REAL: // Set as 32 or 64-bit real if (dwCIMType == CIM_REAL32) { vValue.fltVal = (float)cd.rPropertyRealValue; vValue.vt = VT_R4; } else if (dwCIMType == CIM_REAL64) { vValue.fltVal = (double)cd.rPropertyRealValue; vValue.vt = VT_R8; } break; case WMIDB_STORAGE_IMAGE: if (dwCIMType != CIM_OBJECT) { if (cd.dwBufferLen > 0) { long why[1]; unsigned char t; SAFEARRAYBOUND aBounds[1]; aBounds[0].cElements = cd.dwBufferLen; aBounds[0].lLbound = 0; SAFEARRAY* pArray = SafeArrayCreate(VT_UI1, 1, aBounds); vValue.vt = VT_I1; for (int i = 0; i < cd.dwBufferLen; i++) { why[0] = i; t = cd.pBuffer[i]; hr = SafeArrayPutElement(pArray, why, &t); } vValue.vt = VT_ARRAY|VT_UI1; V_ARRAY(&vValue) = pArray; dwCIMType |= CIM_FLAG_ARRAY; } } else vValue.vt = VT_NULL; break; default: hr = WBEM_E_NOT_SUPPORTED; break; } if (FAILED(hr)) { goto Exit; } // If this is an object (not a reference), // then we need to Get the object and set it in // the variant. Otherwise, the variant is simply // the string path to the object. // =============================================== if (dwCIMType == CIM_OBJECT) { if (bObject) { *bObject = TRUE; goto Exit; } else { if (!bBlobData) { IWmiDbHandle *pHand = NULL; if (vValue.vt == VT_BSTR) { hr = ((CWmiDbSession *)pSession)->GetObject_Internal((LPWSTR)vValue.bstrVal, (DWORD)0, (DWORD)WMIDB_HANDLE_TYPE_COOKIE, NULL, &pHand, pConn); CReleaseMe r4 (pHand); if (SUCCEEDED(hr)) { IWbemClassObject *pEmbed = NULL; hr = ((CWmiDbHandle *)pHand)->QueryInterface_Internal(pConn, (void **)&pEmbed); if (SUCCEEDED(hr)) { VariantClear(&vValue); V_UNKNOWN(&vValue) = (IUnknown *)pEmbed; vValue.vt = VT_UNKNOWN; // VariantClear will release this, right? } } } } else { _IWmiObject *pNew = NULL; hr = ConvertBlobToObject (pNewObj, cd.pBuffer, cd.dwBufferLen, &pNew); if (SUCCEEDED(hr)) { VariantClear(&vValue); V_UNKNOWN(&vValue) = (IUnknown *)pNew; vValue.vt = VT_UNKNOWN; } } } } // For array properties, what we actually need to do is // see if the property exists already. If not, we // initialize the safe array and add the first element. // If so, we simply set the value in the existing array. // ====================================================== if (dwPropFlags & REPDRVR_FLAG_ARRAY && (dwStorage != WMIDB_STORAGE_IMAGE)) { dwCIMType |= CIM_FLAG_ARRAY; VARIANT vTemp; CClearMe c (&vTemp); long lTemp; CIMTYPE cimtype; if (SUCCEEDED(pNewObj->Get(sPropName, 0, &vTemp, &cimtype, &lTemp))) { hr = SetInArray(vTemp, cd.iArrayPos, vValue, cimtype); if (SUCCEEDED(hr)) { hr = pNewObj->Put(sPropName, 0, &vTemp, dwCIMType); bSkip = TRUE; } } } } if (!(dwPropFlags & REPDRVR_FLAG_QUALIFIER) && !(dwPropFlags & REPDRVR_FLAG_IN_PARAM) && !(dwPropFlags & REPDRVR_FLAG_OUT_PARAM) && !bSkip) { if (wcslen(sPropName) == 127) { pNewObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY); BSTR strName = NULL; while (pNewObj->Next(0, &strName, NULL, NULL, NULL) == S_OK) { CFreeMe f (strName); if (!_wcsnicmp(strName, sPropName, 127)) sPropName = strName; } } hr = pNewObj->Put(sPropName, 0, &vValue, dwCIMType); } // If this is a qualifier on a class, get the qualifier set and set the value. else if (dwPropFlags & REPDRVR_FLAG_QUALIFIER ) { if (dRefId != 0) { _bstr_t sProp2; DWORD dwFlags2, dwRefID; hr = pSchema->GetPropertyInfo (dRefId, &sProp2, NULL, NULL, NULL, &dwFlags2, NULL, NULL, &dwRefID); if (SUCCEEDED(hr)) { if (wcslen(sPropName) == 127) { pNewObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY); BSTR strName = NULL; while (pNewObj->Next(0, &strName, NULL, NULL, NULL) == S_OK) { CFreeMe f (strName); if (!_wcsnicmp(strName, sProp2, 127)) sProp2 = strName; } } // This is a property qualifier. See if its a property or a method. // and get all the pertinent info. // This is a qualifier on a method parameter. if (dwFlags2 & REPDRVR_FLAG_IN_PARAM || dwFlags2 & REPDRVR_FLAG_OUT_PARAM) { IWbemClassObject *pIn = NULL; IWbemClassObject *pOut = NULL; IWbemQualifierSet *pQS = NULL; _bstr_t sProp3; hr = pSchema->GetPropertyInfo (dwRefID, &sProp3); if (SUCCEEDED(hr)) { hr = pNewObj->GetMethod(sProp3, 0, &pIn, &pOut); CReleaseMe r5 (pIn), r6 (pOut); if (SUCCEEDED(hr)) { if (dwFlags2 & REPDRVR_FLAG_IN_PARAM && pIn) hr = pIn->GetPropertyQualifierSet(sProp2, &pQS); else if (dwFlags2 & REPDRVR_FLAG_OUT_PARAM && pOut) hr = pOut->GetPropertyQualifierSet(sProp2, &pQS); if (pQS) { CReleaseMe r7 (pQS); if (!_wcsicmp(sPropName, L"id")) sPropName = L"repdrvr_id"; // Sneaky business. // Because we can't set method parameters incrementally, // we need to store the real position IDs as a different // name and switch them back when we're done... if (dwPropFlags & REPDRVR_FLAG_ARRAY) { VARIANT vTemp; BOOL bExists = FALSE; CClearMe c (&vTemp); hr = pQS->Get(sPropName, 0, &vTemp, 0); if (vTemp.vt & CIM_FLAG_ARRAY) bExists = TRUE; hr = SetInArray(vTemp, cd.iArrayPos, vValue, dwCIMType); hr = pQS->Put(sPropName, &vTemp, cd.iFlags); } else hr = pQS->Put(sPropName, &vValue, cd.iFlags); hr = pNewObj->PutMethod(sProp3, 0, pIn, pOut); } } } } // This is a qualifier on a method. else if (dwFlags2 & REPDRVR_FLAG_METHOD) { IWbemQualifierSet *pQS = NULL; hr = pNewObj->GetMethodQualifierSet(sProp2, &pQS); CReleaseMe r4 (pQS); if (SUCCEEDED(hr)) { if (dwPropFlags & REPDRVR_FLAG_ARRAY) { VARIANT vTemp; CClearMe c (&vTemp); BOOL bExists = FALSE; hr = pQS->Get(sPropName, 0, &vTemp, 0); if (vTemp.vt & CIM_FLAG_ARRAY) bExists = TRUE; hr = SetInArray(vTemp, cd.iArrayPos, vValue, dwCIMType); hr = pQS->Put(sPropName, &vTemp, cd.iFlags); } else hr = pQS->Put(sPropName, &vValue, cd.iFlags); } } // This is a qualifier on a property. else { IWbemQualifierSet *pQS = NULL; hr = pNewObj->GetPropertyQualifierSet(sProp2, &pQS); CReleaseMe r4 (pQS); if (SUCCEEDED(hr)) { if (dwPropFlags & REPDRVR_FLAG_ARRAY) { VARIANT vTemp; CClearMe c (&vTemp); BOOL bExists = FALSE; hr = pQS->Get(sPropName, 0, &vTemp, 0); if (vTemp.vt & CIM_FLAG_ARRAY) bExists = TRUE; hr = SetInArray(vTemp, cd.iArrayPos, vValue, dwCIMType); hr = pQS->Put(sPropName, &vTemp, cd.iFlags); } else hr = pQS->Put(sPropName, &vValue, cd.iFlags); } } } } else // Its just a class/instance qualifier. Set it. { IWbemQualifierSet *pQS = NULL; hr = pNewObj->GetQualifierSet(&pQS); CReleaseMe r5 (pQS); if (SUCCEEDED(hr)) { if (dwPropFlags & REPDRVR_FLAG_ARRAY) { VARIANT vTemp; CClearMe c (&vTemp); BOOL bExists = FALSE; hr = pQS->Get(sPropName, 0, &vTemp, 0); if (vTemp.vt & CIM_FLAG_ARRAY) bExists = TRUE; hr = SetInArray(vTemp, cd.iArrayPos, vValue, dwCIMType); hr = pQS->Put(sPropName, &vTemp, cd.iFlags); } else hr = pQS->Put(sPropName, &vValue, cd.iFlags); } } } else if (dwPropFlags & REPDRVR_FLAG_METHOD) { // This is a method. Skip it. } else if (dwPropFlags & REPDRVR_FLAG_IN_PARAM || dwPropFlags & REPDRVR_FLAG_OUT_PARAM ) { _bstr_t sProp2; IWbemClassObject *pTemp = NULL; hr = pSchema->GetPropertyInfo (dRefId, &sProp2); if (SUCCEEDED(hr)) { IWbemClassObject *pOther = NULL; if (dwPropFlags & REPDRVR_FLAG_IN_PARAM) hr = pNewObj->GetMethod(sProp2, 0, &pTemp, &pOther); else hr = pNewObj->GetMethod(sProp2, 0, &pOther, &pTemp); CReleaseMe r1 (pTemp), r2 (pOther); if (SUCCEEDED(hr)) { if (!pTemp) { hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER, IID_IWbemClassObject, (void **)&pTemp); VARIANT vTemp; CClearMe c (&vTemp); vTemp.bstrVal = SysAllocString(L"__Parameters"); vTemp.vt = VT_BSTR; pTemp->Put(L"__Class", NULL, &vTemp, CIM_STRING); } pTemp->Put(sPropName, 0, &vValue, dwCIMType); VARIANT vTemp; CClearMe c2 (&vTemp); long lNumProps = 0; pTemp->Get(L"__Property_Count", NULL, &vTemp, NULL, NULL); lNumProps = vTemp.lVal; if (pOther) { VARIANT vTemp2; CClearMe c2 (&vTemp2); pOther->Get(L"__Property_Count", NULL, &vTemp2, NULL, NULL); lNumProps+= vTemp2.lVal; } if (_wcsicmp(sPropName, L"ReturnValue")) { IWbemQualifierSet *pQS = NULL; pTemp->GetPropertyQualifierSet(sPropName, &pQS); CReleaseMe r5 (pQS); if (pQS) { V_I4(&vTemp) = lNumProps - 1; vTemp.vt = VT_I4; pQS->Put(L"id", &vTemp, 0); } } if (dwPropFlags & REPDRVR_FLAG_IN_PARAM) hr = pNewObj->PutMethod(sProp2, 0, pTemp, pOther); else hr = pNewObj->PutMethod(sProp2, 0, pOther, pTemp); hr = pSchema->SetAuxiliaryPropertyInfo(cd.iPropertyId, L"", dRefId); } } } } Exit: VariantClear(&vValue); return hr; } // structs for open rowsets. //*************************************************************************** // // AddColumnToTable // //*************************************************************************** // Helper functions for setting up reusable accessors. HRESULT AddColumnToTable (CESEConnection *pConn, JET_TABLEID tableid, LPSTR lpTableName, LPWSTR lpColumnName, DWORD _colid, DWORD datatype, DWORD options, DWORD prec, JET_COLUMNID *colid) { HRESULT hr = WBEM_S_NO_ERROR; char *pColName = GetAnsiString(lpColumnName); if (!pColName) return WBEM_E_OUT_OF_MEMORY; CDeleteMe d (pColName); JET_COLUMNDEF columnDef; JET_ERR err = JET_errSuccess; err = JetGetColumnInfo(pConn->GetSessionID(), pConn->GetDBID(), lpTableName, pColName, &columnDef, sizeof(JET_COLUMNDEF), 0); if (err < JET_errSuccess) { columnDef.cp = 1200; // Unicode? Otherwise, its 1252. columnDef.wCountry = 1; columnDef.langid = 1033; columnDef.wCollate = 0; columnDef.cbStruct = sizeof(JET_COLUMNDEF); columnDef.columnid = _colid; columnDef.coltyp = datatype; columnDef.grbit = options ; columnDef.cbMax = prec; err = JetAddColumn(pConn->GetSessionID(), tableid, pColName, &columnDef, "", 0, colid); } else *colid = columnDef.columnid; hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // UpdateDBVersion // //*************************************************************************** HRESULT UpdateDBVersion (CSQLConnection *_pConn, DWORD iVersion) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; const LPSTR lpTbl = "DBVersion"; JET_SESID session = pConn->GetSessionID(); JET_DBID dbid = pConn->GetDBID(); JET_TABLEID tableid; JET_ERR err = JetOpenTable (session, dbid, lpTbl, NULL, 0, JET_bitTableUpdatable, &tableid); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); err = JetCreateTable(session, dbid, lpTbl, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } JET_COLUMNID colid; hr = AddColumnToTable(pConn, tableid, lpTbl, L"Version", 0, JET_coltypLong, JET_bitColumnNotNULL, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) { // This is a one-row table. err = JetMove(session, tableid, JET_MoveFirst, 0); if (err >= JET_errSuccess) err = JetPrepareUpdate(session, tableid, JET_prepReplace); else err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, colid, &iVersion, sizeof(DWORD), 0, NULL ); err = JetUpdate(session, tableid, NULL, 0, NULL ); } } JetCloseTable(session, tableid); hr = CSQLExecute::GetWMIError(err); Exit: return hr; } //*************************************************************************** // // SetupObjectMapAccessor // //*************************************************************************** HRESULT SetupObjectMapAccessor (CSQLConnection *_pConn) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; const LPSTR lpTbl = "ObjectMap"; if (!pConn->GetTableID(L"ObjectMap")) { JET_SESID session; JET_TABLEID tableid; BOOL bCreate = FALSE; // Get the session and table ID // and create columns as needed. session = pConn->GetSessionID(); JET_DBID dbid = pConn->GetDBID(); JET_ERR err = JetOpenTable (session, dbid, lpTbl, NULL, 0, JET_bitTableUpdatable, &tableid); CSQLExecute::GetWMIError(err); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); bCreate = TRUE; err = JetCreateTable(session, dbid, lpTbl, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } else pConn->SetTableID(L"ObjectMap", tableid); JET_COLUMNID colid; // Unfortunately, they don't support a numeric type, // so we have to use currency. hr = AddColumnToTable(pConn, tableid, lpTbl, L"ObjectId", OBJECTMAP_COL_OBJECTID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, OBJECTMAP_COL_OBJECTID, colid); else if (err != JET_errColumnDuplicate) goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ObjectPath", OBJECTMAP_COL_OBJECTPATH, JET_coltypText, 0, MAX_STRING_WIDTH, &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, OBJECTMAP_COL_OBJECTPATH, colid); else if (err != JET_errColumnDuplicate) goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ObjectKey", OBJECTMAP_COL_OBJECTKEY, JET_coltypText, 0, MAX_STRING_WIDTH, &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, OBJECTMAP_COL_OBJECTKEY, colid); else if (err != JET_errColumnDuplicate) goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ReferenceCount", OBJECTMAP_COL_REFERENCECOUNT, JET_coltypLong, 0, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, OBJECTMAP_COL_REFERENCECOUNT, colid); else if (err != JET_errColumnDuplicate) goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ObjectState", OBJECTMAP_COL_OBJECTSTATE, JET_coltypLong, 0, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, OBJECTMAP_COL_OBJECTSTATE, colid); else if (err != JET_errColumnDuplicate) goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ClassId", OBJECTMAP_COL_CLASSID, JET_coltypCurrency, 0, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, OBJECTMAP_COL_CLASSID, colid); else if (err != JET_errColumnDuplicate) goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ObjectFlags", OBJECTMAP_COL_OBJECTFLAGS, JET_coltypLong, 0, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, OBJECTMAP_COL_OBJECTFLAGS, colid); else if (err != JET_errColumnDuplicate) goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ObjectScopeId", OBJECTMAP_COL_OBJECTSCOPEID, JET_coltypCurrency, 0, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, OBJECTMAP_COL_OBJECTSCOPEID, colid); else if (err != JET_errColumnDuplicate) goto Exit; err = JetCreateIndex(session, tableid, "ObjectMap_PK", JET_bitIndexPrimary | JET_bitIndexUnique,"+ObjectId\0", 11, 100); if (err >= JET_errSuccess || err == JET_errIndexHasPrimary) { err = JetCreateIndex(session, tableid, "ObjectScopeId_idx", JET_bitIndexDisallowNull ,"+ObjectScopeId\0", 16, 100); if (err >= JET_errSuccess|| err == JET_errIndexDuplicate) { err = JetCreateIndex(session, tableid, "ObjectClassId_idx", JET_bitIndexDisallowNull ,"+ClassId\0", 10, 100); if (err == JET_errIndexDuplicate) err = JET_errSuccess; } } if (err >= JET_errSuccess && bCreate) { err = JetCloseTable(session, tableid); if (err >= JET_errSuccess) { hr = SetupObjectMapAccessor(_pConn); } } if (err) hr = CSQLExecute::GetWMIError(err); } Exit: return hr; } //*************************************************************************** // // GetObjectMapData // //*************************************************************************** HRESULT GetObjectMapData (CSQLConnection *_pConn, JET_SESID session, JET_TABLEID tableid, OBJECTMAP &oj) { HRESULT hr = WBEM_E_FAILED; oj.Clear(); unsigned long lLen; wchar_t buff[1024]; CESEConnection *pConn = (CESEConnection *)_pConn; oj.dObjectId = 0; JET_ERR err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTID), &oj.dObjectId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTKEY), buff, MAX_STRING_WIDTH, &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (lLen) { buff[lLen/2] = L'\0'; oj.sObjectKey = SysAllocString(buff); if (wcslen(buff) && !oj.sObjectKey) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; } } err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTPATH), buff, MAX_STRING_WIDTH, &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (lLen) { buff[lLen/2] = L'\0'; oj.sObjectPath = SysAllocString(buff); if (wcslen(buff) && !oj.sObjectPath) { hr = WBEM_E_OUT_OF_MEMORY; oj.Clear(); goto exit; } } err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_REFERENCECOUNT), &oj.iRefCount, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_CLASSID), &oj.dClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTFLAGS), &oj.iObjectFlags, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTSCOPEID), &oj.dObjectScopeId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTSTATE), &oj.iObjectState, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; hr = WBEM_S_NO_ERROR; exit: return hr; } //*************************************************************************** // // OpenEnum_ObjectMap // //*************************************************************************** HRESULT OpenEnum_ObjectMap (CSQLConnection *_pConn, OBJECTMAP &oj) { HRESULT hr = WBEM_E_NOT_FOUND; // Locate the first row for this ObjectID and bind the data. CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupObjectMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ObjectMap"); JET_ERR err = JetSetCurrentIndex(session, tableid, "ObjectMap_PK"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMove(session, tableid, JET_MoveFirst, 0); if (err == JET_errSuccess) hr = GetObjectMapData(pConn, session, tableid, oj); } } return hr; } //*************************************************************************** // // GetFirst_ObjectMap // //*************************************************************************** HRESULT GetFirst_ObjectMap (CSQLConnection *_pConn, SQL_ID dObjectId, OBJECTMAP &oj) { HRESULT hr = WBEM_E_NOT_FOUND; // Locate the first row for this ObjectID and bind the data. CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupObjectMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ObjectMap"); // Use the default index // Grab the first row, // and stuff it into the OBJECTMAP object. JET_ERR err = JetSetCurrentIndex(session, tableid, "ObjectMap_PK"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) hr = GetObjectMapData(pConn, session, tableid, oj); else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_ObjectMapByScope // //*************************************************************************** HRESULT GetFirst_ObjectMapByScope (CSQLConnection *_pConn, SQL_ID dScopeId, OBJECTMAP &oj, DWORD seektype = JET_bitSeekEQ) { HRESULT hr = WBEM_S_NO_ERROR; // Locate the first row for this ObjectID and bind the data. CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupObjectMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ObjectMap"); // Use the default index // Grab the first row, // and stuff it into the OBJECTMAP object. JET_ERR err = JetSetCurrentIndex(session, tableid, "ObjectScopeId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dScopeId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, seektype ); if (err == JET_errSuccess) { if (seektype == JET_bitSeekEQ) { err = JetMakeKey(session, tableid, &dScopeId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); } else if (seektype == JET_bitSeekLT || seektype == JET_bitSeekLE ) { err = JetMakeKey(session, tableid, &dScopeId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) err = JetSetIndexRange(session, tableid, JET_bitRangeUpperLimit); } if (err == JET_errSuccess) hr = GetObjectMapData(pConn, session, tableid, oj); else hr = WBEM_E_NOT_FOUND; } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_ObjectMapByClass // //*************************************************************************** HRESULT GetFirst_ObjectMapByClass (CSQLConnection *_pConn, SQL_ID dClassId, OBJECTMAP &oj) { HRESULT hr = WBEM_S_NO_ERROR; // Locate the first row for this ObjectID and bind the data. CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupObjectMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ObjectMap"); // Use the default index // Grab the first row, // and stuff it into the OBJECTMAP object. JET_ERR err = JetSetCurrentIndex(session, tableid, "ObjectClassId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dClassId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dClassId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetObjectMapData(pConn, session, tableid, oj); } else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetNext_ObjectMap // //*************************************************************************** HRESULT GetNext_ObjectMap (CSQLConnection *_pConn, OBJECTMAP &oj) { HRESULT hr = 0; oj.Clear(); JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ObjectMap"); err = JetMove(session, tableid, JET_MoveNext, 0); if (err == JET_errSuccess) hr = GetObjectMapData(pConn, session, tableid, oj); else hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // UpdateObjectMap // //*************************************************************************** HRESULT UpdateObjectMap (CSQLConnection *_pConn, OBJECTMAP oj, BOOL bDelete = FALSE) { HRESULT hr = WBEM_S_NO_ERROR; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupObjectMapAccessor(pConn); JET_ERR err = JET_errSuccess; if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ObjectMap"); err = JetSetCurrentIndex(session, tableid, "ObjectMap_PK"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &oj.dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { if (err == JET_errSuccess) { err = JetPrepareUpdate(session, tableid, JET_prepReplace); if (err == JET_errSuccess) { if (oj.sObjectPath) err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTPATH), oj.sObjectPath, wcslen(oj.sObjectPath)*2+2, 0, NULL ); else err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTPATH), NULL, 0, 0, NULL ); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_CLASSID), &oj.dClassId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTSCOPEID), &oj.dObjectScopeId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; if (oj.sObjectKey) err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTKEY), oj.sObjectKey, wcslen(oj.sObjectKey)*2+2, 0, NULL); else err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTKEY), NULL, 0, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_REFERENCECOUNT), &oj.iRefCount, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTFLAGS), &oj.iObjectFlags, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTSTATE), &oj.iObjectState, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; if (bDelete) err = JetDelete(session, tableid); else err = JetUpdate(session, tableid, NULL, 0, NULL ); } } } } } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // InsertObjectMap // //*************************************************************************** HRESULT InsertObjectMap(CSQLConnection *_pConn, SQL_ID dObjectId, LPCWSTR lpKey, DWORD iState, LPCWSTR lpObjectPath, SQL_ID dScopeID, DWORD iClassFlags, DWORD iRefCount, SQL_ID dClassId, BOOL bInsert) { DEBUGTRACE((LOG_WBEMCORE, "InsertObjectMap %S\n", lpObjectPath)); HRESULT hr = 0; JET_ERR err = 0; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupObjectMapAccessor(pConn); if (SUCCEEDED(hr)) { OBJECTMAP oj; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ObjectMap"); if (FAILED(GetFirst_ObjectMap(_pConn, dObjectId, oj))) { err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTID), &dObjectId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTPATH), lpObjectPath, wcslen(lpObjectPath)*2+2, 0, NULL ); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_CLASSID), &dClassId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTSCOPEID), &dScopeID, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTKEY), lpKey, wcslen(lpKey)*2+2, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_REFERENCECOUNT), &iRefCount, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTFLAGS), &iClassFlags, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, OBJECTMAP_COL_OBJECTSTATE), &iState, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetUpdate(session, tableid, NULL, 0, NULL ); hr = WBEM_S_NO_ERROR; } } else if (!bInsert) { oj.Clear(); oj.dObjectId = dObjectId; oj.dClassId = dClassId; oj.sObjectPath = SysAllocString(lpObjectPath); oj.sObjectKey = SysAllocString(lpKey); if (!oj.sObjectPath || !oj.sObjectKey) { hr = WBEM_E_OUT_OF_MEMORY; oj.Clear(); goto Exit; } oj.iRefCount = iRefCount; oj.iObjectFlags = iClassFlags; oj.dObjectScopeId = dScopeID; oj.iObjectState = iState; hr = UpdateObjectMap(pConn, oj, FALSE); oj.Clear(); } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // SetupScopeMapAccessor // //*************************************************************************** HRESULT SetupScopeMapAccessor (CSQLConnection *_pConn) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; if (!pConn->GetTableID(L"ScopeMap")) { JET_SESID session; JET_TABLEID tableid; JET_DBID dbid; const LPSTR lpTbl = "ScopeMap"; BOOL bCreate = FALSE; // Get the session and table ID // and create columns as needed. session = pConn->GetSessionID(); dbid = pConn->GetDBID(); JET_ERR err = JetOpenTable (session, dbid, lpTbl, NULL, 0, JET_bitTableUpdatable, &tableid); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); bCreate = TRUE; err = JetCreateTable(session, dbid, lpTbl, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } else pConn->SetTableID(L"ScopeMap", tableid); JET_COLUMNID colid; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ObjectId", SCOPEMAP_COL_OBJECTID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, SCOPEMAP_COL_OBJECTID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ScopePath", SCOPEMAP_COL_SCOPEPATH, JET_coltypLongBinary, 0, 0, &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, SCOPEMAP_COL_SCOPEPATH, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ParentId", SCOPEMAP_COL_PARENTID, JET_coltypCurrency, 0, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, SCOPEMAP_COL_PARENTID, colid); else goto Exit; err = JetCreateIndex(session, tableid, "ScopeMap_PK", JET_bitIndexPrimary | JET_bitIndexUnique,"+ObjectId\0", 11, 100); if ((err >= JET_errSuccess || err == JET_errIndexHasPrimary) && bCreate) { err = JetCloseTable(session, tableid); if (err >= JET_errSuccess) { hr = SetupScopeMapAccessor(_pConn); } } if (err == JET_errIndexHasPrimary) err = 0; if (err) hr = CSQLExecute::GetWMIError(err); } Exit: return hr; } //*************************************************************************** // // GetScopeMapData // //*************************************************************************** HRESULT GetScopeMapData (CSQLConnection *_pConn, JET_SESID session, JET_TABLEID tableid, SCOPEMAP &sm) { HRESULT hr = WBEM_E_FAILED; CESEConnection *pConn = (CESEConnection *)_pConn; unsigned long lLen; wchar_t buff[1024]; BYTE buff2[1024]; sm.Clear(); JET_ERR err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, SCOPEMAP_COL_OBJECTID), &sm.dObjectId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, SCOPEMAP_COL_SCOPEPATH), buff2, MAX_STRING_WIDTH, &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (lLen) { BYTE *pBuff = new BYTE [lLen]; if (pBuff) { err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, SCOPEMAP_COL_SCOPEPATH), pBuff, lLen, &lLen, JET_bitRetrieveCopy, NULL); sm.sScopePath = SysAllocString((LPWSTR)pBuff); if (!sm.sScopePath) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; } } else hr = WBEM_E_OUT_OF_MEMORY; } err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, SCOPEMAP_COL_PARENTID), &sm.dParentId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; hr = WBEM_S_NO_ERROR; exit: return hr; } //*************************************************************************** // // OpenEnum_ScopeMap // //*************************************************************************** HRESULT OpenEnum_ScopeMap (CSQLConnection *_pConn, SCOPEMAP &cd) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupScopeMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ScopeMap"); // Use the default index // Grab the first row, // and stuff it into the SCOPEMAP object. JetSetIndexRange(session, tableid, JET_bitRangeRemove); JET_ERR err = JetSetCurrentIndex(session, tableid, "ScopeMap_PK"); if (err == JET_errSuccess) { err = JetMove(session, tableid, JET_MoveFirst, 0); if (err == JET_errSuccess) hr = GetScopeMapData(pConn, session, tableid, cd); } } return hr; } //*************************************************************************** // // GetFirst_ScopeMap // //*************************************************************************** HRESULT GetFirst_ScopeMap (CSQLConnection *_pConn, SQL_ID dScopeId, SCOPEMAP &cd) { HRESULT hr = WBEM_E_NOT_FOUND; // Locate the first row for this ObjectID and bind the data. CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupScopeMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ScopeMap"); // Use the default index // Grab the first row, // and stuff it into the SCOPEMAP object. JET_ERR err = JetSetCurrentIndex(session, tableid, "ScopeMap_PK"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dScopeId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dScopeId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { if (err == JET_errSuccess) hr = GetScopeMapData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; } } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetNext_ScopeMap // //*************************************************************************** HRESULT GetNext_ScopeMap (CSQLConnection *_pConn, SCOPEMAP &cd) { HRESULT hr = 0; cd.Clear(); JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ScopeMap"); err = JetMove(session, tableid, JET_MoveNext, 0); if (err == JET_errSuccess) hr = GetScopeMapData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // UpdateScopeMap // //*************************************************************************** HRESULT UpdateScopeMap (CSQLConnection *_pConn, SCOPEMAP cd, BOOL bDelete = FALSE) { HRESULT hr = WBEM_S_NO_ERROR; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = 0; hr = SetupScopeMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ScopeMap"); err = JetSetCurrentIndex(session, tableid, "ScopeMap_PK"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &cd.dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { if (err == JET_errSuccess) { err = JetPrepareUpdate(session, tableid, JET_prepReplace); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, SCOPEMAP_COL_PARENTID), &cd.dParentId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; if (cd.sScopePath) err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, SCOPEMAP_COL_SCOPEPATH), cd.sScopePath, wcslen(cd.sScopePath)*2+2, 0, NULL); if (err < JET_errSuccess) goto Exit; if (bDelete) err = JetDelete(session, tableid); else err = JetUpdate(session, tableid, NULL, 0, NULL ); } } } } } } Exit: hr = CSQLExecute::GetWMIError(err); if (bDelete && hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; return hr; } //*************************************************************************** // // InsertScopeMap_Internal // //*************************************************************************** HRESULT InsertScopeMap_Internal(CSQLConnection *_pConn, SQL_ID dObjectId, LPCWSTR lpPath, SQL_ID dParentId) { JET_ERR err = 0; HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupScopeMapAccessor(pConn); if (SUCCEEDED(hr)) { SCOPEMAP oj; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ScopeMap"); if (FAILED(GetFirst_ScopeMap(_pConn, dObjectId, oj))) { int iLen = 2; BYTE *pBuff = (BYTE *)lpPath; if (lpPath) { iLen += wcslen(lpPath)*2; } err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, SCOPEMAP_COL_OBJECTID), &dObjectId, sizeof(__int64), 0, NULL ); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, SCOPEMAP_COL_SCOPEPATH), pBuff, iLen, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, SCOPEMAP_COL_PARENTID), &dParentId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetUpdate(session, tableid, NULL, 0, NULL ); hr = WBEM_S_NO_ERROR; } oj.Clear(); } else { oj.Clear(); oj.dObjectId = dObjectId; oj.dParentId = dParentId; oj.sScopePath = SysAllocString(lpPath); if (!oj.sScopePath) { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } hr = UpdateScopeMap(pConn, oj, FALSE); SysFreeString(oj.sScopePath); // The buffer is released by the caller. } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // DeleteScopeMap // //*************************************************************************** HRESULT DeleteScopeMap(CSQLConnection *_pConn, SQL_ID dObjectId) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupScopeMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ScopeMap"); JET_ERR err = JetSetCurrentIndex(session, tableid, "ScopeMap_PK"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetDelete(session, tableid); } } } hr = CSQLExecute::GetWMIError(err); if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; } return hr; } //*************************************************************************** // // SetupClassMapAccessor // //*************************************************************************** HRESULT SetupClassMapAccessor (CSQLConnection *_pConn) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; if (!pConn->GetTableID(L"ClassMap")) { JET_SESID session; JET_TABLEID tableid; JET_DBID dbid; const LPSTR lpTbl = "ClassMap"; BOOL bCreate = FALSE; // Get the session and table ID // and create columns as needed. session = pConn->GetSessionID(); dbid = pConn->GetDBID(); JET_ERR err = JetOpenTable (session, dbid, lpTbl, NULL, 0, JET_bitTableUpdatable, &tableid); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); bCreate = TRUE; err = JetCreateTable(session, dbid, lpTbl, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } else pConn->SetTableID(L"ClassMap", tableid); JET_COLUMNID colid; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ClassId", CLASSMAP_COL_CLASSID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSMAP_COL_CLASSID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ClassName", CLASSMAP_COL_CLASSNAME, JET_coltypText, 0, MAX_STRING_WIDTH, &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSMAP_COL_CLASSNAME, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"SuperClassId", CLASSMAP_COL_SUPERCLASSID, JET_coltypCurrency, 0, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSMAP_COL_SUPERCLASSID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"DynastyId", CLASSMAP_COL_DYNASTYID, JET_coltypCurrency, 0, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSMAP_COL_DYNASTYID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ClassBlob", CLASSMAP_COL_CLASSBUFFER, JET_coltypLongBinary, 0, 0, &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSMAP_COL_CLASSBUFFER, colid); else goto Exit; err = JetCreateIndex(session, tableid, "ClassMap_PK", JET_bitIndexPrimary | JET_bitIndexUnique,"+ClassId\0", 10, 100); if (err >= JET_errSuccess || err == JET_errIndexHasPrimary) { err = JetCreateIndex(session, tableid, "SuperClassId_idx", JET_bitIndexDisallowNull ,"+SuperClassId\0", 15, 100); if (err == JET_errIndexDuplicate) err = JET_errSuccess; err = JetCreateIndex(session, tableid, "DynastyId_idx", JET_bitIndexDisallowNull, "+DynastyId\0", 12, 80); if (err == JET_errIndexDuplicate) err = JET_errSuccess; err = JetCreateIndex(session, tableid, "ClassName_idx", JET_bitIndexDisallowNull, "+ClassName\0", 12, 80); if (err == JET_errIndexDuplicate) err = JET_errSuccess; } if (err >= JET_errSuccess && bCreate) { err = JetCloseTable(session, tableid); if (err >= JET_errSuccess) { hr = SetupClassMapAccessor(_pConn); } } if (err) hr = CSQLExecute::GetWMIError(err); } Exit: return hr; } //*************************************************************************** // // GetClassMapData // //*************************************************************************** HRESULT GetClassMapData (CSQLConnection *_pConn, JET_SESID session, JET_TABLEID tableid, CLASSMAP &oj) { HRESULT hr = WBEM_E_FAILED; CESEConnection *pConn = (CESEConnection *)_pConn; unsigned long lLen; wchar_t buff[1024]; BYTE buff2[1024]; oj.dClassId = 0; oj.dSuperClassId = 0; oj.dDynastyId = 0; oj.Clear(); JET_ERR err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_CLASSID), &oj.dClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_CLASSNAME), buff, MAX_STRING_WIDTH, &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (lLen) { buff[lLen/2] = L'\0'; oj.sClassName = SysAllocString(buff); if (!oj.sClassName) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; } } err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_SUPERCLASSID), &oj.dSuperClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_DYNASTYID), &oj.dDynastyId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_CLASSBUFFER), buff2, MAX_STRING_WIDTH, &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (lLen) { oj.dwBufferLen = lLen; BYTE *pBuff = new BYTE [lLen]; if (pBuff) { err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_CLASSBUFFER), pBuff, lLen, &oj.dwBufferLen, JET_bitRetrieveCopy, NULL); oj.pClassBuffer = pBuff; } else { hr = WBEM_E_OUT_OF_MEMORY; oj.Clear(); goto exit; } } hr = WBEM_S_NO_ERROR; exit: return hr; } //*************************************************************************** // // OpenEnum_ClassMap // //*************************************************************************** HRESULT OpenEnum_ClassMap (CSQLConnection *_pConn, CLASSMAP &cd) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupClassMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassMap"); // Use the default index // Grab the first row, // and stuff it into the OBJECTMAP object. JetSetIndexRange(session, tableid, JET_bitRangeRemove); JET_ERR err = JetSetCurrentIndex(session, tableid, "ClassMap_PK"); if (err == JET_errSuccess) { err = JetMove(session, tableid, JET_MoveFirst, 0); if (err == JET_errSuccess) hr = GetClassMapData(pConn, session, tableid, cd); } } return hr; } //*************************************************************************** // // GetFirst_ClassMap // //*************************************************************************** HRESULT GetFirst_ClassMap (CSQLConnection *_pConn, SQL_ID dClassId, CLASSMAP &cd) { HRESULT hr = WBEM_E_NOT_FOUND; // Locate the first row for this ObjectID and bind the data. CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupClassMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassMap"); // Use the default index // Grab the first row, // and stuff it into the OBJECTMAP object. JET_ERR err = JetSetCurrentIndex(session, tableid, "ClassMap_PK"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dClassId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dClassId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { if (err == JET_errSuccess) hr = GetClassMapData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; } } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_ClassMapBySuperClass // //*************************************************************************** HRESULT GetFirst_ClassMapBySuperClass (CSQLConnection *_pConn, SQL_ID dSuperClassId, CLASSMAP &cd) { HRESULT hr = WBEM_E_NOT_FOUND; // Locate the first row for this ObjectID and bind the data. CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupClassMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassMap"); JET_ERR err = JetSetCurrentIndex(session, tableid, "SuperClassId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dSuperClassId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dSuperClassId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetClassMapData(pConn, session, tableid, cd); } else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_ClassMapByDynasty // //*************************************************************************** HRESULT GetFirst_ClassMapByDynasty (CSQLConnection *_pConn, SQL_ID dDynastyId, CLASSMAP &cd) { HRESULT hr = WBEM_E_NOT_FOUND; // Locate the first row for this ObjectID and bind the data. CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupClassMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassMap"); JET_ERR err = JetSetCurrentIndex(session, tableid, "DynastyId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dDynastyId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dDynastyId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetClassMapData(pConn, session, tableid, cd); } else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_ClassMapByName // //*************************************************************************** HRESULT GetFirst_ClassMapByName (CSQLConnection *_pConn, LPCWSTR lpName, CLASSMAP &cd) { HRESULT hr = WBEM_E_NOT_FOUND; if (!lpName) return WBEM_E_INVALID_PARAMETER; // Locate the first row for this ObjectID and bind the data. CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupClassMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassMap"); JET_ERR err = JetSetCurrentIndex(session, tableid, "ClassName_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, lpName, wcslen(lpName)*2+2, JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, lpName, wcslen(lpName)*2+2, JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetClassMapData(pConn, session, tableid, cd); } else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetNext_ClassMap // //*************************************************************************** HRESULT GetNext_ClassMap (CSQLConnection *_pConn, CLASSMAP &cd) { HRESULT hr = 0; cd.Clear(); JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassMap"); err = JetMove(session, tableid, JET_MoveNext, 0); if (err == JET_errSuccess) hr = GetClassMapData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // UpdateClassMap // //*************************************************************************** HRESULT UpdateClassMap (CSQLConnection *_pConn, CLASSMAP cd, BOOL bDelete = FALSE) { HRESULT hr = WBEM_S_NO_ERROR; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = 0; hr = SetupClassMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassMap"); err = JetSetCurrentIndex(session, tableid, "ClassMap_PK"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &cd.dClassId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { if (err == JET_errSuccess) { err = JetPrepareUpdate(session, tableid, JET_prepReplace); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_CLASSNAME), cd.sClassName, wcslen(cd.sClassName)*2+2, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_SUPERCLASSID), &cd.dSuperClassId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_DYNASTYID), &cd.dDynastyId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; if (cd.dwBufferLen) err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_CLASSBUFFER), cd.pClassBuffer, cd.dwBufferLen, 0, NULL); else err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_CLASSBUFFER), NULL, 0, 0, NULL); if (err < JET_errSuccess) goto Exit; if (bDelete) err = JetDelete(session, tableid); else err = JetUpdate(session, tableid, NULL, 0, NULL ); } } } } } } Exit: hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // InsertClassMap // //*************************************************************************** HRESULT InsertClassMap(CSQLConnection *_pConn, SQL_ID dClassId, LPCWSTR lpClassName, SQL_ID dSuperClassId, SQL_ID dDynasty, BYTE *pBuff, DWORD dwBufferLen, BOOL bInsert) { if (!dSuperClassId && dClassId != 1) dSuperClassId = 1; JET_ERR err = 0; HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupClassMapAccessor(pConn); if (SUCCEEDED(hr)) { CLASSMAP oj; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassMap"); if (FAILED(GetFirst_ClassMap(_pConn, dClassId, oj))) { err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_CLASSID), &dClassId, sizeof(__int64), 0, NULL ); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_CLASSNAME), lpClassName, wcslen(lpClassName)*2+2, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_SUPERCLASSID), &dSuperClassId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_DYNASTYID), &dDynasty, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSMAP_COL_CLASSBUFFER), pBuff, dwBufferLen, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetUpdate(session, tableid, NULL, 0, NULL ); hr = WBEM_S_NO_ERROR; } oj.Clear(); } else if (!bInsert) { oj.Clear(); oj.dClassId = dClassId; oj.dSuperClassId = dSuperClassId; oj.dDynastyId = dDynasty; oj.sClassName = SysAllocString(lpClassName); if (!oj.sClassName) { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } oj.pClassBuffer = pBuff; oj.dwBufferLen = dwBufferLen; hr = UpdateClassMap(pConn, oj, FALSE); SysFreeString(oj.sClassName); // The buffer is released by the caller. } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // SetupPropertyMapAccessor // //*************************************************************************** HRESULT SetupPropertyMapAccessor (CSQLConnection *_pConn) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; if (!pConn->GetTableID(L"PropertyMap")) { JET_SESID session; JET_DBID dbid; JET_TABLEID tableid; const LPSTR lpTbl = "PropertyMap"; BOOL bCreate = FALSE; // Get the session and table ID // and create columns as needed. session = pConn->GetSessionID(); dbid = pConn->GetDBID(); JET_ERR err = JetOpenTable (session, dbid, lpTbl, NULL, 0, JET_bitTableUpdatable, &tableid); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); bCreate = TRUE; err = JetCreateTable(session, dbid, lpTbl, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } else pConn->SetTableID(L"PropertyMap", tableid); JET_COLUMNID colid; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ClassId", PROPERTYMAP_COL_CLASSID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, PROPERTYMAP_COL_CLASSID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"PropertyId", PROPERTYMAP_COL_PROPERTYID, JET_coltypLong, JET_bitColumnNotNULL|JET_bitColumnAutoincrement, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, PROPERTYMAP_COL_PROPERTYID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"StorageTypeId", PROPERTYMAP_COL_STORAGETYPEID, JET_coltypLong, 0, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, PROPERTYMAP_COL_STORAGETYPEID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"CIMTypeId", PROPERTYMAP_COL_CIMTYPEID, JET_coltypLong, 0, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, PROPERTYMAP_COL_CIMTYPEID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"PropertyName", PROPERTYMAP_COL_PROPERTYNAME, JET_coltypText, JET_bitColumnNotNULL, MAX_STRING_WIDTH, &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, PROPERTYMAP_COL_PROPERTYNAME, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"Flags", PROPERTYMAP_COL_FLAGS, JET_coltypLong, 0, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, PROPERTYMAP_COL_FLAGS, colid); else goto Exit; err = JetCreateIndex(session, tableid, "PropertyMap_PK", JET_bitIndexPrimary | JET_bitIndexUnique,"+PropertyId\0", 13, 100); if (err >= JET_errSuccess || err == JET_errIndexHasPrimary) { err = JetCreateIndex(session, tableid, "ClassId_idx", JET_bitIndexDisallowNull ,"+ClassId\0", 10, 100); if (err >= JET_errSuccess || err == JET_errIndexDuplicate) err = JET_errSuccess; else hr = CSQLExecute::GetWMIError(err); } if (err >= JET_errSuccess && bCreate) { err = JetCloseTable(session, tableid); if (err >= JET_errSuccess) { hr = SetupPropertyMapAccessor(_pConn); } } if (err) hr = CSQLExecute::GetWMIError(err); } Exit: return hr; } //*************************************************************************** // // GetPropertyMapData // //*************************************************************************** HRESULT GetPropertyMapData (CSQLConnection *_pConn, JET_SESID session, JET_TABLEID tableid, PROPERTYMAP &oj) { HRESULT hr = WBEM_E_FAILED; oj.Clear(); CESEConnection *pConn = (CESEConnection *)_pConn; unsigned long lLen; wchar_t buff[1024]; oj.iPropertyId = 0; JET_ERR err = JET_errSuccess; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_PROPERTYID), &oj.iPropertyId, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_PROPERTYNAME), buff, MAX_STRING_WIDTH, &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (lLen) { buff[lLen/2] = L'\0'; oj.sPropertyName = SysAllocString(buff); if (!oj.sPropertyName) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; } } err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_CLASSID), &oj.dClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_STORAGETYPEID), &oj.iStorageTypeId, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_CIMTYPEID), &oj.iCIMTypeId, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_FLAGS), &oj.iFlags, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; hr = WBEM_S_NO_ERROR; exit: return hr; } //*************************************************************************** // // GetFirst_PropertyMap // //*************************************************************************** HRESULT GetFirst_PropertyMap (CSQLConnection *_pConn, DWORD iPropertyId, PROPERTYMAP &pm) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupPropertyMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"PropertyMap"); JET_ERR err = JetSetCurrentIndex(session, tableid, "PropertyMap_PK"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) hr = GetPropertyMapData(pConn, session, tableid, pm); else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_PropertyMapByClass // //*************************************************************************** HRESULT GetFirst_PropertyMapByClass (CSQLConnection *_pConn, SQL_ID dClassId, PROPERTYMAP &pm) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupPropertyMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"PropertyMap"); JET_ERR err = JetSetCurrentIndex(session, tableid, "ClassId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dClassId, sizeof(SQL_ID), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dClassId, sizeof(SQL_ID), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) hr = GetPropertyMapData(pConn, session, tableid, pm); else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetNext_PropertyMap // //*************************************************************************** HRESULT GetNext_PropertyMap (CSQLConnection *_pConn, PROPERTYMAP &pm) { HRESULT hr = 0; pm.Clear(); CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = JET_errSuccess; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"PropertyMap"); err = JetMove(session, tableid, JET_MoveNext, 0); if (err == JET_errSuccess) hr = GetPropertyMapData(pConn, session, tableid, pm); else hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // UpdatePropertyMap // //*************************************************************************** HRESULT UpdatePropertyMap(CSQLConnection *_pConn, PROPERTYMAP pm, BOOL bDelete = FALSE) { HRESULT hr = WBEM_S_NO_ERROR; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = 0; hr = SetupPropertyMapAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"PropertyMap"); err = JetSetCurrentIndex(session, tableid, "PropertyMap_PK"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &pm.iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { if (err == JET_errSuccess) { err = JetPrepareUpdate(session, tableid, JET_prepReplace); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_PROPERTYNAME), pm.sPropertyName, wcslen(pm.sPropertyName)*2+2, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_CLASSID), &pm.dClassId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_STORAGETYPEID), &pm.iStorageTypeId, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_FLAGS), &pm.iFlags, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_CIMTYPEID), &pm.iCIMTypeId, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; if (bDelete) err = JetDelete(session, tableid); else err = JetUpdate(session, tableid, NULL, 0, NULL ); } } } } } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // InsertPropertyMap // //*************************************************************************** HRESULT InsertPropertyMap (CSQLConnection *_pConn, DWORD &iPropID, SQL_ID dClassId, DWORD iStorageTypeId, DWORD iCIMTypeId, LPCWSTR lpPropName, DWORD iFlags, BOOL bInsert) { JET_ERR err = 0; HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupPropertyMapAccessor(pConn); if (SUCCEEDED(hr)) { if (bInsert) iPropID = 0; unsigned long lLen; PROPERTYMAP pm; DWORD dwOldFlags = 0; JET_SESID session = pConn->GetSessionID(); BOOL bExists = FALSE; JET_TABLEID tableid = pConn->GetTableID(L"PropertyMap"); hr = GetFirst_PropertyMapByClass(_pConn, dClassId, pm); while (SUCCEEDED(hr)) { if (!_wcsicmp(pm.sPropertyName, lpPropName)) { BOOL bMatch = TRUE; if ((iFlags & REPDRVR_FLAG_NONPROP) == (pm.iFlags & REPDRVR_FLAG_NONPROP)) { if (iFlags & REPDRVR_FLAG_NONPROP) { if (iStorageTypeId != pm.iStorageTypeId) bMatch = FALSE; } if (bMatch) { iPropID = pm.iPropertyId; dwOldFlags = pm.iFlags; pm.Clear(); bExists = TRUE; break; } } } hr = GetNext_PropertyMap(_pConn, pm); if (pm.dClassId != dClassId) break; } hr = WBEM_S_NO_ERROR; if (!bExists) { err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { // Now retrieve the auto-incremented ID... err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_PROPERTYID), &iPropID, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL) ; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_PROPERTYNAME), lpPropName, wcslen(lpPropName)*2+2, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_CLASSID), &dClassId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_STORAGETYPEID), &iStorageTypeId, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_FLAGS), &iFlags, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, PROPERTYMAP_COL_CIMTYPEID), &iCIMTypeId, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetUpdate(session, tableid, NULL, 0, NULL ); hr = WBEM_S_NO_ERROR; } } else if (!bInsert) { pm.Clear(); pm.iPropertyId = iPropID; pm.sPropertyName = SysAllocString(lpPropName); if (!pm.sPropertyName) { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } pm.dClassId = dClassId; pm.iStorageTypeId = iStorageTypeId; pm.iCIMTypeId = iCIMTypeId; pm.iFlags = iFlags; hr = UpdatePropertyMap(pConn, pm, FALSE); pm.Clear(); } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // SetupClassKeysAccessor // //*************************************************************************** HRESULT SetupClassKeysAccessor (CSQLConnection *_pConn) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; if (!pConn->GetTableID(L"ClassKeys")) { JET_SESID session; JET_TABLEID tableid; JET_DBID dbid; const LPSTR lpTbl = "ClassKeys"; BOOL bCreate = FALSE; // Get the session and table ID // and create columns as needed. session = pConn->GetSessionID(); dbid = pConn->GetDBID(); JET_ERR err = JetOpenTable (session, dbid, lpTbl, NULL, 0, JET_bitTableUpdatable, &tableid); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); bCreate = TRUE; err = JetCreateTable(session, dbid, lpTbl, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } else pConn->SetTableID(L"ClassKeys", tableid); JET_COLUMNID colid; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ClassId", CLASSKEYS_COL_CLASSID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSKEYS_COL_CLASSID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"PropertyId", CLASSKEYS_COL_PROPERTYID, JET_coltypLong, 0, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSKEYS_COL_PROPERTYID, colid); else goto Exit; err = JetCreateIndex(session, tableid, "ClassId_idx", JET_bitIndexDisallowNull,"+ClassId\0", 10, 100); if (err >= JET_errSuccess || err == JET_errIndexDuplicate) { err = JetCreateIndex(session, tableid, "PropertyId_idx", JET_bitIndexDisallowNull ,"+PropertyId\0", 13, 100); if (err == JET_errIndexDuplicate) err = JET_errSuccess; } if (err >= JET_errSuccess && bCreate) { err = JetCloseTable(session, tableid); if (err >= JET_errSuccess) { hr = SetupClassKeysAccessor(_pConn); } } if (err) hr = CSQLExecute::GetWMIError(err); } Exit: return hr; } //*************************************************************************** // // GetClassKeysData // //*************************************************************************** HRESULT GetClassKeysData (CSQLConnection *_pConn, JET_SESID session, JET_TABLEID tableid, CLASSKEYS &oj) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; unsigned long lLen; oj.iPropertyId = 0; JET_ERR err = JET_errSuccess; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSKEYS_COL_PROPERTYID), &oj.iPropertyId, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSKEYS_COL_CLASSID), &oj.dClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; hr = WBEM_S_NO_ERROR; exit: return hr; } //*************************************************************************** // // GetFirst_ClassKeys // //*************************************************************************** HRESULT GetFirst_ClassKeys (CSQLConnection *_pConn, SQL_ID dClassId, CLASSKEYS &cd) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupClassKeysAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassKeys"); JET_ERR err = JetSetCurrentIndex(session, tableid, "ClassId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dClassId, sizeof(SQL_ID), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dClassId, sizeof(SQL_ID), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) hr = GetClassKeysData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_ClassKeysByPropertyId // //*************************************************************************** HRESULT GetFirst_ClassKeysByPropertyId (CSQLConnection *_pConn, DWORD dwPropertyId, CLASSKEYS &cd) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupClassKeysAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassKeys"); JET_ERR err = JetSetCurrentIndex(session, tableid, "PropertyId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dwPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dwPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) hr = GetClassKeysData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetNext_ClassKeys // //*************************************************************************** HRESULT GetNext_ClassKeys (CSQLConnection *_pConn, CLASSKEYS &cd) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = JET_errSuccess; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassKeys"); err = JetMove(session, tableid, JET_MoveNext, 0); if (err == JET_errSuccess) hr = GetClassKeysData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // UpdateClassKeys // //*************************************************************************** HRESULT UpdateClassKeys(CSQLConnection *_pConn, CLASSKEYS cd, BOOL bDelete = FALSE) { HRESULT hr = 0; JET_ERR err = 0; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupClassKeysAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassKeys"); err = JetSetCurrentIndex(session, tableid, "PropertyId_idx"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &cd.iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &cd.iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); while (err == JET_errSuccess) { CLASSKEYS ck; ULONG lLen; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSKEYS_COL_CLASSID), &ck.dClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; if (ck.dClassId == cd.dClassId) { if (bDelete) err = JetDelete(session, tableid); break; } err = JetMove(session, tableid, JET_MoveNext, 0); } } } } } } Exit: hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // InsertClassKeys // //*************************************************************************** HRESULT InsertClassKeys (CSQLConnection *_pConn, SQL_ID dClassId, DWORD dwPropertyId, BOOL bInsert) { HRESULT hr = 0; JET_ERR err = 0; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupClassKeysAccessor(pConn); if (SUCCEEDED(hr)) { CLASSKEYS oj; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassKeys"); oj.dClassId = dClassId; oj.iPropertyId = dwPropertyId; hr = UpdateClassKeys(pConn, oj, FALSE); if (FAILED(hr)) { err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSKEYS_COL_CLASSID), &dClassId, sizeof(__int64), 0, NULL ); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSKEYS_COL_PROPERTYID), &dwPropertyId, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetUpdate(session, tableid, NULL, 0, NULL ); } hr = WBEM_S_NO_ERROR; } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // DeleteClassKeys // //*************************************************************************** HRESULT DeleteClassKeys (CSQLConnection *_pConn, SQL_ID dClassId, DWORD dwPropertyId = 0) { HRESULT hr = 0; CLASSKEYS ck; if (dwPropertyId) hr = GetFirst_ClassKeysByPropertyId(_pConn, dwPropertyId, ck); else hr = GetFirst_ClassKeys(_pConn, dClassId, ck); while (SUCCEEDED(hr)) { hr = UpdateClassKeys(_pConn, ck, TRUE); hr = GetNext_ClassKeys(_pConn, ck); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; return hr; } //*************************************************************************** // // SetupReferencePropertiesAccessor // //*************************************************************************** HRESULT SetupReferencePropertiesAccessor (CSQLConnection *_pConn) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; if (!pConn->GetTableID(L"ReferenceProperties")) { JET_SESID session; JET_TABLEID tableid; JET_DBID dbid; const LPSTR lpTbl = "ReferenceProperties"; BOOL bCreate = FALSE; // Get the session and table ID // and create columns as needed. session = pConn->GetSessionID(); dbid = pConn->GetDBID(); JET_ERR err = JetOpenTable (session, dbid, lpTbl, NULL, 0, JET_bitTableUpdatable, &tableid); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); bCreate = TRUE; err = JetCreateTable(session, dbid, lpTbl, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } else pConn->SetTableID(L"ReferenceProperties", tableid); JET_COLUMNID colid; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ClassId", REFPROPS_COL_CLASSID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, REFPROPS_COL_CLASSID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"PropertyId", REFPROPS_COL_PROPERTYID, JET_coltypLong, 0, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, REFPROPS_COL_PROPERTYID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"RefClassId", REFPROPS_COL_REFCLASSID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, REFPROPS_COL_REFCLASSID, colid); else goto Exit; err = JetCreateIndex(session, tableid, "ClassId_idx", JET_bitIndexDisallowNull,"+ClassId\0", 10, 100); if (err >= JET_errSuccess || err == JET_errIndexDuplicate) { err = JetCreateIndex(session, tableid, "RefClassId_idx", JET_bitIndexDisallowNull,"+RefClassId\0", 13, 100); if (err >= JET_errSuccess || err == JET_errIndexDuplicate) { err = JetCreateIndex(session, tableid, "PropertyId_idx", JET_bitIndexDisallowNull ,"+PropertyId\0", 13, 100); if (err == JET_errIndexDuplicate) err = JET_errSuccess; } } if (err >= JET_errSuccess && bCreate) { err = JetCloseTable(session, tableid); if (err >= JET_errSuccess) { hr = SetupReferencePropertiesAccessor(_pConn); } } if (err) hr = CSQLExecute::GetWMIError(err); } Exit: return hr; } //*************************************************************************** // // GetReferencePropertiesData // //*************************************************************************** HRESULT GetReferencePropertiesData (CSQLConnection *_pConn, JET_SESID session, JET_TABLEID tableid, REFERENCEPROPERTIES &oj) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; unsigned long lLen; oj.iPropertyId = 0; JET_ERR err = JET_errSuccess; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, REFPROPS_COL_PROPERTYID), &oj.iPropertyId, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, REFPROPS_COL_CLASSID), &oj.dClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, REFPROPS_COL_REFCLASSID), &oj.dRefClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; hr = WBEM_S_NO_ERROR; exit: return hr; } //*************************************************************************** // // GetFirst_ReferenceProperties // //*************************************************************************** HRESULT GetFirst_ReferenceProperties (CSQLConnection *_pConn, DWORD dwPropertyId, REFERENCEPROPERTIES &cd) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupReferencePropertiesAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ReferenceProperties"); JET_ERR err = JetSetCurrentIndex(session, tableid, "PropertyId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dwPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dwPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) hr = GetReferencePropertiesData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_ReferencePropertiesByRef // //*************************************************************************** HRESULT GetFirst_ReferencePropertiesByRef (CSQLConnection *_pConn, SQL_ID dRefClassId, REFERENCEPROPERTIES &cd) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupReferencePropertiesAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ReferenceProperties"); JET_ERR err = JetSetCurrentIndex(session, tableid, "RefClassId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dRefClassId, sizeof(SQL_ID), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dRefClassId, sizeof(SQL_ID), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) hr = GetReferencePropertiesData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_ReferencePropertiesByClass // //*************************************************************************** HRESULT GetFirst_ReferencePropertiesByClass (CSQLConnection *_pConn, SQL_ID dClassId, REFERENCEPROPERTIES &cd) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupReferencePropertiesAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ReferenceProperties"); JET_ERR err = JetSetCurrentIndex(session, tableid, "ClassId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dClassId, sizeof(SQL_ID), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dClassId, sizeof(SQL_ID), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) hr = GetReferencePropertiesData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; } } } } if (SUCCEEDED(hr) && err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetNext_ReferenceProperties // //*************************************************************************** HRESULT GetNext_ReferenceProperties (CSQLConnection *_pConn, REFERENCEPROPERTIES &cd) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = JET_errSuccess; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ReferenceProperties"); err = JetMove(session, tableid, JET_MoveNext, 0); if (err == JET_errSuccess) hr = GetReferencePropertiesData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // UpdateReferenceProperties // //*************************************************************************** HRESULT UpdateReferenceProperties(CSQLConnection *_pConn, REFERENCEPROPERTIES cd, BOOL bDelete = FALSE, BOOL bAllowMultiple = FALSE) { HRESULT hr = 0; JET_ERR err = 0; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupReferencePropertiesAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ReferenceProperties"); err = JetSetCurrentIndex(session, tableid, "PropertyId_idx"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &cd.iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &cd.iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); while (err == JET_errSuccess) { REFERENCEPROPERTIES ck; ULONG lLen; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, REFPROPS_COL_CLASSID), &ck.dClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; if (ck.dClassId == cd.dClassId) { BOOL bFound = TRUE; if (bAllowMultiple) { err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, REFPROPS_COL_REFCLASSID), &ck.dRefClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; if (ck.dRefClassId != cd.dRefClassId) bFound = FALSE; } if (bFound) { err = JetPrepareUpdate(session, tableid, JET_prepReplace); err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, REFPROPS_COL_REFCLASSID), &ck.dRefClassId, sizeof(__int64), 0, NULL ); if (err < JET_errSuccess) goto Exit; if (bDelete) err = JetDelete(session, tableid); else err = JetUpdate(session, tableid, 0, NULL, 0); break; } } err = JetMove(session, tableid, JET_MoveNext, 0); } } } } } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // InsertReferenceProperties // //*************************************************************************** HRESULT InsertReferenceProperties (CSQLConnection *_pConn, SQL_ID dClassId, DWORD dwPropertyId, SQL_ID dRefClassId, BOOL bAllowMultiple = FALSE) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = 0; hr = SetupReferencePropertiesAccessor(pConn); if (SUCCEEDED(hr)) { REFERENCEPROPERTIES oj; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ReferenceProperties"); BOOL bFound = FALSE; hr = GetFirst_ReferenceProperties(_pConn, dClassId, oj); while (SUCCEEDED(hr)) { if (oj.iPropertyId == dwPropertyId) { bFound = TRUE; if (bAllowMultiple) { if (dRefClassId != oj.dRefClassId) bFound = FALSE; } if (bFound) break; } hr = GetNext_ReferenceProperties(_pConn, oj); } if (!bFound) { err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, REFPROPS_COL_CLASSID), &dClassId, sizeof(__int64), 0, NULL ); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, REFPROPS_COL_REFCLASSID), &dRefClassId, sizeof(__int64), 0, NULL ); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, REFPROPS_COL_PROPERTYID), &dwPropertyId, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetUpdate(session, tableid, NULL, 0, NULL ); } hr = WBEM_S_NO_ERROR; } else { oj.dClassId = dClassId; oj.iPropertyId = dwPropertyId; oj.dRefClassId = dRefClassId; hr = UpdateReferenceProperties(pConn, oj, FALSE, bAllowMultiple); } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // DeleteReferenceProperties // //*************************************************************************** HRESULT DeleteReferenceProperties (CSQLConnection *_pConn, DWORD dwPropertyId, SQL_ID dClassId = 0) { HRESULT hr = 0; REFERENCEPROPERTIES ck; hr = GetFirst_ReferenceProperties(_pConn, dwPropertyId, ck); while (SUCCEEDED(hr)) { BOOL bMatch = TRUE; if (dClassId && dClassId != ck.dClassId) bMatch = FALSE; if (bMatch) hr = UpdateReferenceProperties(_pConn, ck, TRUE); hr = GetNext_ReferenceProperties(_pConn, ck); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; return hr; } //*************************************************************************** // // DeleteReferencePropertiesByClass // //*************************************************************************** HRESULT DeleteReferencePropertiesByClass (CSQLConnection *_pConn, SQL_ID dClassId) { HRESULT hr = 0; REFERENCEPROPERTIES ck; hr = GetFirst_ReferencePropertiesByClass(_pConn, dClassId, ck); while (SUCCEEDED(hr)) { hr = UpdateReferenceProperties(_pConn, ck, TRUE); hr = GetNext_ReferenceProperties(_pConn, ck); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; return hr; } //*************************************************************************** // // SetupClassDataAccessor // //*************************************************************************** HRESULT SetupClassDataAccessor (CSQLConnection *_pConn) { HRESULT hr = 0; JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; if (!pConn->GetTableID(L"ClassData")) { JET_SESID session; JET_TABLEID tableid; JET_DBID dbid; const LPSTR lpTbl = "ClassData"; BOOL bCreate = FALSE; // Get the session and table ID // and create columns as needed. session = pConn->GetSessionID(); dbid = pConn->GetDBID(); err = JetOpenTable (session, dbid, lpTbl, NULL, 0, JET_bitTableUpdatable, &tableid); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); bCreate = TRUE; err = JetCreateTable(session, dbid, lpTbl, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } else pConn->SetTableID(L"ClassData", tableid); JET_COLUMNID colid; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ObjectId", CLASSDATA_COL_OBJECTID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSDATA_COL_OBJECTID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"PropertyId", CLASSDATA_COL_PROPERTYID, JET_coltypLong, JET_bitColumnNotNULL, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSDATA_COL_PROPERTYID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ArrayPos", CLASSDATA_COL_ARRAYPOS, JET_coltypLong, 0, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSDATA_COL_ARRAYPOS, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"QfrPos", CLASSDATA_COL_QFRPOS, JET_coltypLong, 0, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSDATA_COL_QFRPOS, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ClassId", CLASSDATA_COL_CLASSID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSDATA_COL_CLASSID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"RefClassId", CLASSDATA_COL_REFCLASSID, JET_coltypCurrency, 0, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSDATA_COL_REFCLASSID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"RefId", CLASSDATA_COL_REFID, JET_coltypCurrency, 0, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSDATA_COL_REFID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"Flags", CLASSDATA_COL_FLAGS, JET_coltypLong, 0, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSDATA_COL_FLAGS, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"PropertyStringValue", CLASSDATA_COL_STRINGVALUE, JET_coltypText, 0, MAX_STRING_WIDTH, &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSDATA_COL_STRINGVALUE, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"PropertyNumericValue", CLASSDATA_COL_NUMERICVALUE, JET_coltypCurrency, 0, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSDATA_COL_NUMERICVALUE, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"PropertyRealValue", CLASSDATA_COL_REALVALUE, JET_coltypIEEEDouble, 0, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSDATA_COL_REALVALUE, colid); else goto Exit; err = JetCreateIndex(session, tableid, "ObjectId_idx", JET_bitIndexDisallowNull,"+ObjectId\0", 11, 100); if (err >= JET_errSuccess || err == JET_errIndexDuplicate) { err = JetCreateIndex(session, tableid, "RefId_idx", JET_bitIndexDisallowNull ,"+RefId\0", 8, 100); if (err >= JET_errSuccess || err == JET_errIndexDuplicate) { err = JetCreateIndex(session, tableid, "PropertyId_idx", JET_bitIndexDisallowNull ,"+PropertyId\0", 13, 100); if (err == JET_errIndexDuplicate) err = JET_errSuccess; } } if (err >= JET_errSuccess && bCreate) { err = JetCloseTable(session, tableid); if (err >= JET_errSuccess) { hr = SetupClassDataAccessor(_pConn); } } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // GetClassData // //*************************************************************************** HRESULT GetClassData (CSQLConnection *_pConn, JET_SESID session, JET_TABLEID tableid, CLASSDATA &oj, BOOL bMinimum=FALSE, CSchemaCache *pCache = NULL) { HRESULT hr = WBEM_E_FAILED; CESEConnection *pConn = (CESEConnection *)_pConn; unsigned long lLen; wchar_t buff[1024]; oj.Clear(); oj.dRefId = 0, oj.dPropertyNumericValue = 0, oj.rPropertyRealValue = 0; JET_ERR err = JET_errSuccess; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_PROPERTYID), &oj.iPropertyId, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (!bMinimum) { err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_OBJECTID), &oj.dObjectId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_CLASSID), &oj.dClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REFCLASSID), &oj.dRefClassId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_QFRPOS), &oj.iQfrPos, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; } err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_FLAGS), &oj.iFlags, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_ARRAYPOS), &oj.iArrayPos, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REFID), &oj.dRefId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (!lLen) oj.dRefId = 0; if (!(oj.iFlags & ESE_FLAG_NULL)) { DWORD dwPropFlags = 0; DWORD dwStorage = 0; if (pCache) { hr = pCache->GetPropertyInfo (oj.iPropertyId, NULL, NULL, &dwStorage, NULL, &dwPropFlags); } if (SUCCEEDED(hr) && dwStorage != 0) { switch(dwStorage) { case WMIDB_STORAGE_REFERENCE: case WMIDB_STORAGE_STRING: err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_STRINGVALUE), buff, MAX_STRING_WIDTH, &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (lLen) { buff[lLen/2] = L'\0'; oj.sPropertyStringValue = SysAllocString(buff); if (wcslen(buff) && !oj.sPropertyStringValue) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; } } break; case WMIDB_STORAGE_NUMERIC: err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_NUMERICVALUE), &oj.dPropertyNumericValue, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (!lLen) oj.dPropertyNumericValue = 0; break; case WMIDB_STORAGE_REAL: err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REALVALUE), &oj.rPropertyRealValue, sizeof(double), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (!lLen) oj.rPropertyRealValue = 0; break; default: hr = WBEM_E_INVALID_OPERATION; break; } } else { err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_STRINGVALUE), buff, MAX_STRING_WIDTH, &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (lLen) { buff[lLen/2] = L'\0'; oj.sPropertyStringValue = SysAllocString(buff); if (wcslen(buff) && !oj.sPropertyStringValue) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; } } err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_NUMERICVALUE), &oj.dPropertyNumericValue, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (!lLen) oj.dPropertyNumericValue = 0; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REALVALUE), &oj.rPropertyRealValue, sizeof(double), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (!lLen) oj.rPropertyRealValue = 0; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REFID), &oj.dRefId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (!lLen) oj.dRefId = 0; } } hr = WBEM_S_NO_ERROR; exit: return hr; } //*************************************************************************** // // GetFirst_ClassData // //*************************************************************************** HRESULT GetFirst_ClassData (CSQLConnection *_pConn, SQL_ID dId, CLASSDATA &cd, DWORD iPropertyId, BOOL bMinimum, CSchemaCache *pCache) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupClassDataAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassData"); JET_ERR err = JetSetCurrentIndex(session, tableid, "ObjectId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { while (err == JET_errSuccess) { if (FAILED(GetClassData(pConn, session, tableid, cd, bMinimum, pCache))) break; else if (iPropertyId == -1 || cd.iPropertyId == iPropertyId) { hr = WBEM_S_NO_ERROR; break; } err = JetMove(session, tableid, JET_MoveNext, 0); } } } } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_ClassDataByRefId // //*************************************************************************** HRESULT GetFirst_ClassDataByRefId (CSQLConnection *_pConn, SQL_ID dRefId, CLASSDATA &cd) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupClassDataAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassData"); JET_ERR err = JetSetCurrentIndex(session, tableid, "RefId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dRefId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dRefId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetClassData(pConn, session, tableid, cd); } } } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_ClassDataByPropertyId // //*************************************************************************** HRESULT GetFirst_ClassDataByPropertyId (CSQLConnection *_pConn, DWORD iPropertyId, CLASSDATA &cd) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupClassDataAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassData"); JET_ERR err = JetSetCurrentIndex(session, tableid, "PropertyId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetClassData(pConn, session, tableid, cd); } } } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetNext_ClassData // //*************************************************************************** HRESULT GetNext_ClassData (CSQLConnection *_pConn, CLASSDATA &cd, DWORD iPropertyId, BOOL bMinimum, CSchemaCache *pCache) { HRESULT hr = 0; cd.Clear(); CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = JET_errSuccess; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassData"); err = JetMove(session, tableid, JET_MoveNext, 0); if (err == JET_errSuccess) hr = GetClassData(pConn, session, tableid, cd, bMinimum, pCache); else hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // UpdateClassData_Internal // //*************************************************************************** HRESULT UpdateClassData_Internal(CSQLConnection *_pConn, CLASSDATA cd, BOOL bDelete = FALSE) { HRESULT hr = WBEM_S_NO_ERROR; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = 0; hr = SetupClassDataAccessor(pConn); if (SUCCEEDED(hr)) { unsigned long lLen; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassData"); err = JetSetCurrentIndex(session, tableid, "ObjectId_idx"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &cd.dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &cd.dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); while (err == JET_errSuccess) { CLASSDATA cd2; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_OBJECTID), &cd2.dObjectId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_ARRAYPOS), &cd2.iArrayPos, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_QFRPOS), &cd2.iQfrPos, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_PROPERTYID), &cd2.iPropertyId, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; if (cd.dObjectId == cd2.dObjectId && cd.iPropertyId == cd2.iPropertyId && cd.iQfrPos == cd2.iQfrPos && cd.iArrayPos == cd2.iArrayPos) { err = JetPrepareUpdate(session, tableid, JET_prepReplace); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_OBJECTID), &cd.dObjectId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_CLASSID), &cd.dClassId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REFID), &cd.dRefId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_NUMERICVALUE), &cd.dPropertyNumericValue, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REFCLASSID), &cd.dRefClassId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_ARRAYPOS), &cd.iArrayPos, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_QFRPOS), &cd.iQfrPos, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_FLAGS), &cd.iFlags, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_PROPERTYID), &cd.iPropertyId, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REALVALUE), &cd.rPropertyRealValue, sizeof(double), 0, NULL); if (err < JET_errSuccess) goto Exit; if (cd.sPropertyStringValue) err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_STRINGVALUE), cd.sPropertyStringValue, wcslen(cd.sPropertyStringValue)*2+2, 0, NULL); else err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_STRINGVALUE), NULL, 0, 0, NULL); if (err < JET_errSuccess) goto Exit; if (bDelete) err = JetDelete(session, tableid); else err = JetUpdate(session, tableid, NULL, 0, NULL ); } break; } else err = JetMove(session, tableid, JET_MoveNext, 0); } } } } } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // InsertClassData_Internal // //*************************************************************************** HRESULT InsertClassData_Internal (CSQLConnection *_pConn, SQL_ID dObjectId, DWORD iPropID, DWORD iArrayPos, DWORD iQfrPos, SQL_ID dClassId, LPCWSTR lpStringValue, SQL_ID dNumericValue, double fRealValue, DWORD iFlags, SQL_ID dRefId, SQL_ID dRefClassId, BOOL bIsNull) { HRESULT hr = 0; JET_ERR err = 0; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupClassDataAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassData"); CLASSDATA cd; cd.dObjectId = dObjectId; cd.dClassId = dClassId; cd.iArrayPos = iArrayPos; cd.iQfrPos = iQfrPos; cd.iPropertyId = iPropID; cd.iFlags = iFlags; if (bIsNull) cd.iFlags |= ESE_FLAG_NULL; if (!bIsNull) { cd.dRefId = dRefId; cd.dRefClassId = dRefClassId; cd.rPropertyRealValue = fRealValue; cd.dPropertyNumericValue = dNumericValue; if (lpStringValue) { LPWSTR lpVal = StripQuotes2((LPWSTR)lpStringValue); CDeleteMe d (lpVal); cd.sPropertyStringValue = SysAllocString(lpVal); if (!cd.sPropertyStringValue) { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } } else cd.sPropertyStringValue = NULL; } else { cd.dRefId =0; cd.dRefClassId = 0; cd.rPropertyRealValue = 0; cd.dPropertyNumericValue = 0; cd.sPropertyStringValue = NULL; } hr = UpdateClassData_Internal(pConn, cd, FALSE); if (FAILED(hr)) { err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_OBJECTID), &dObjectId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_CLASSID), &dClassId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; // NOTE: This can't be null, because we have an index on it... err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REFID), &dRefId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; if (!bIsNull) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_NUMERICVALUE), &dNumericValue, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REFCLASSID), &dRefClassId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REALVALUE), &fRealValue, sizeof(double), 0, NULL); if (err < JET_errSuccess) goto Exit; if (cd.sPropertyStringValue) err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_STRINGVALUE), cd.sPropertyStringValue, wcslen(cd.sPropertyStringValue)*2+2, 0, NULL); } else { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_NUMERICVALUE), NULL, 0, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REFCLASSID), NULL, 0, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_REALVALUE), NULL, 0, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_STRINGVALUE), NULL, 0, 0, NULL); } err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_ARRAYPOS), &iArrayPos, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_QFRPOS), &iQfrPos, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_FLAGS), &cd.iFlags, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSDATA_COL_PROPERTYID), &iPropID, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetUpdate(session, tableid, NULL, 0, NULL ); } } hr = WBEM_S_NO_ERROR; cd.Clear(); } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // SetupClassImagesAccessor // //*************************************************************************** HRESULT SetupClassImagesAccessor (CSQLConnection *_pConn) { HRESULT hr = 0; JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; if (!pConn->GetTableID(L"ClassImages")) { JET_SESID session; JET_TABLEID tableid; JET_DBID dbid; BOOL bCreate = FALSE; const LPSTR lpTbl = "ClassImages"; // Get the session and table ID // and create columns as needed. session = pConn->GetSessionID(); dbid = pConn->GetDBID(); err = JetOpenTable (session, dbid, lpTbl, NULL, 0, JET_bitTableUpdatable, &tableid); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); bCreate = TRUE; err = JetCreateTable(session, dbid, lpTbl, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } else pConn->SetTableID(L"ClassImages", tableid); JET_COLUMNID colid; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ObjectId", CLASSIMAGES_COL_OBJECTID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSIMAGES_COL_OBJECTID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"PropertyId", CLASSIMAGES_COL_PROPERTYID, JET_coltypLong, JET_bitColumnNotNULL, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSIMAGES_COL_PROPERTYID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ArrayPos", CLASSIMAGES_COL_ARRAYPOS, JET_coltypLong, JET_bitColumnNotNULL, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSIMAGES_COL_ARRAYPOS, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"PropertyImageValue", CLASSIMAGES_COL_IMAGEVALUE, JET_coltypLongBinary, 0, 0, &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CLASSIMAGES_COL_IMAGEVALUE, colid); else goto Exit; err = JetCreateIndex(session, tableid, "ObjectId_idx", JET_bitIndexDisallowNull,"+ObjectId\0", 11, 100); if (err >= JET_errSuccess ||err == JET_errIndexDuplicate) { err = JetCreateIndex(session, tableid, "PropertyId_idx", JET_bitIndexDisallowNull ,"+PropertyId\0", 13, 100); if (err == JET_errIndexDuplicate) err = JET_errSuccess; } if (err >= JET_errSuccess && bCreate) { err = JetCloseTable(session, tableid); if (err >= JET_errSuccess) { hr = SetupClassImagesAccessor(_pConn); } } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // GetClassImagesData // //*************************************************************************** HRESULT GetClassImagesData (CSQLConnection *_pConn, JET_SESID session, JET_TABLEID tableid, CLASSIMAGES &oj) { HRESULT hr = WBEM_E_FAILED; JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; unsigned long lLen; BYTE buff[128]; oj.Clear(); err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_OBJECTID), &oj.dObjectId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_PROPERTYID), &oj.iPropertyId, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_ARRAYPOS), &oj.iArrayPos, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_IMAGEVALUE), buff, 128, &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if(lLen > 0) { oj.pBuffer = new BYTE[lLen]; if (oj.pBuffer) { oj.dwBufferLen = lLen; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_IMAGEVALUE), oj.pBuffer, oj.dwBufferLen, &lLen, JET_bitRetrieveCopy, NULL); } else hr = WBEM_E_OUT_OF_MEMORY; } hr = WBEM_S_NO_ERROR; exit: return hr; } //*************************************************************************** // // GetFirst_ClassImages // //*************************************************************************** HRESULT GetFirst_ClassImages (CSQLConnection *_pConn, SQL_ID dId, CLASSIMAGES &cd) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupClassImagesAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassImages"); JET_ERR err = JetSetCurrentIndex(session, tableid, "ObjectId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetClassImagesData(pConn, session, tableid, cd); } } } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_ClassImagesByPropertyId // //*************************************************************************** HRESULT GetFirst_ClassImagesByPropertyId (CSQLConnection *_pConn, DWORD iPropertyId, CLASSIMAGES &cd) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupClassImagesAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassImages"); JET_ERR err = JetSetCurrentIndex(session, tableid, "PropertyId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetClassImagesData(pConn, session, tableid, cd); } } } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetNext_ClassImages // //*************************************************************************** HRESULT GetNext_ClassImages (CSQLConnection *_pConn, CLASSIMAGES &cd) { HRESULT hr = 0; cd.Clear(); CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = JET_errSuccess; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassImages"); err = JetMove(session, tableid, JET_MoveNext, 0); if (err == JET_errSuccess) hr = GetClassImagesData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // UpdateClassImages // //*************************************************************************** HRESULT UpdateClassImages (CSQLConnection *_pConn, CLASSIMAGES cd, BOOL bDelete = FALSE) { HRESULT hr = WBEM_S_NO_ERROR; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = 0; hr = SetupClassImagesAccessor(pConn); if (SUCCEEDED(hr)) { unsigned long lLen; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassImages"); err = JetSetCurrentIndex(session, tableid, "ObjectId_idx"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &cd.dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &cd.dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); while (err == JET_errSuccess) { CLASSIMAGES cd2; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_OBJECTID), &cd2.dObjectId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_ARRAYPOS), &cd2.iArrayPos, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_PROPERTYID), &cd2.iPropertyId, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; if (cd.dObjectId == cd2.dObjectId && cd.iPropertyId == cd2.iPropertyId && cd.iArrayPos == cd2.iArrayPos) { err = JetPrepareUpdate(session, tableid, JET_prepReplace); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_OBJECTID), &cd.dObjectId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_ARRAYPOS), &cd.iArrayPos, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_PROPERTYID), &cd.iPropertyId, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_IMAGEVALUE), cd.pBuffer, cd.dwBufferLen, 0, NULL); if (err < JET_errSuccess) goto Exit; if (bDelete) err = JetDelete(session, tableid); else err = JetUpdate(session, tableid, NULL, 0, NULL ); } break; } else err = JetMove(session, tableid, JET_MoveNext, 0); } } } } } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // InsertClassImages // //*************************************************************************** HRESULT InsertClassImages (CSQLConnection *_pConn, SQL_ID dObjectId, DWORD iPropID, DWORD iArrayPos, BYTE *pStream = NULL, DWORD dwLength = 0) { HRESULT hr = 0; JET_ERR err = 0; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupClassImagesAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ClassImages"); CLASSIMAGES cd; cd.dObjectId = dObjectId; cd.iArrayPos = iArrayPos; cd.iPropertyId = iPropID; cd.pBuffer = pStream; cd.dwBufferLen = dwLength; hr = UpdateClassImages(pConn, cd, FALSE); if (FAILED(hr)) { err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_OBJECTID), &dObjectId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_ARRAYPOS), &iArrayPos, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_PROPERTYID), &iPropID, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CLASSIMAGES_COL_IMAGEVALUE), pStream, dwLength, 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetUpdate(session, tableid, NULL, 0, NULL ); } } hr = WBEM_S_NO_ERROR; } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // SetupIndexDataAccessor // //*************************************************************************** HRESULT SetupIndexDataAccessor (CSQLConnection *_pConn, DWORD dwStorage, DWORD &dwPos, LPWSTR * lpTableName) { HRESULT hr = 0; char szTable [30]; wchar_t wTable[30]; CESEConnection *pConn = (CESEConnection *)_pConn; JET_COLTYP coltype; JET_TABLEID tableid; JET_ERR err = JET_errSuccess; switch(dwStorage) { case WMIDB_STORAGE_STRING: dwPos = SQL_POS_INDEXSTRING; tableid = pConn->GetTableID(L"IndexStringData"); strcpy(szTable, "IndexStringData"); coltype = JET_coltypText; break; case WMIDB_STORAGE_REFERENCE: dwPos = SQL_POS_INDEXREF; strcpy(szTable, "IndexRefData"); tableid = pConn->GetTableID(L"IndexRefData"); coltype = JET_coltypCurrency; break; case WMIDB_STORAGE_NUMERIC: dwPos = SQL_POS_INDEXNUMERIC; strcpy(szTable, "IndexNumericData"); tableid = pConn->GetTableID(L"IndexNumericData"); coltype = JET_coltypCurrency; break; case WMIDB_STORAGE_REAL: dwPos = SQL_POS_INDEXREAL; coltype = JET_coltypIEEEDouble; strcpy(szTable, "IndexRealData"); tableid = pConn->GetTableID(L"IndexRealData"); break; default: dwPos = 0; break; } if (dwPos != 0) { swprintf(wTable, L"%S", szTable); if (!tableid) { JET_SESID session; JET_DBID dbid; BOOL bCreate = FALSE; // Get the session and table ID // and create columns as needed. session = pConn->GetSessionID(); dbid = pConn->GetDBID(); err = JetOpenTable (session, dbid, szTable, NULL, 0, JET_bitTableUpdatable, &tableid); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); bCreate = TRUE; err = JetCreateTable(session, dbid, szTable, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } else pConn->SetTableID(wTable, tableid); JET_COLUMNID colid; hr = AddColumnToTable(pConn, tableid, szTable, L"ObjectId", INDEXTBL_COL_OBJECTID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, INDEXTBL_COL_OBJECTID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, szTable, L"PropertyId", INDEXTBL_COL_PROPERTYID, JET_coltypLong, JET_bitColumnNotNULL, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, INDEXTBL_COL_PROPERTYID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, szTable, L"ArrayPos", INDEXTBL_COL_ARRAYPOS, JET_coltypLong, JET_bitColumnNotNULL, sizeof(DWORD), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, INDEXTBL_COL_ARRAYPOS, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, szTable, L"IndexValue", INDEXTBL_COL_INDEXVALUE, coltype, 0, 2, &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, INDEXTBL_COL_INDEXVALUE, colid); else goto Exit; err = JetCreateIndex(session, tableid, "ObjectId_idx", JET_bitIndexDisallowNull,"+ObjectId\0", 11, 100); if (err >= JET_errSuccess || JET_errIndexDuplicate == err) { err = JetCreateIndex(session, tableid, "PropertyId_idx", JET_bitIndexDisallowNull ,"+PropertyId\0", 13, 100); if (err >= JET_errSuccess || JET_errIndexDuplicate == err) { err = JetCreateIndex(session, tableid, "IndexValue_idx", JET_bitIndexDisallowNull ,"+IndexValue\0", 13, 80); if (err == JET_errIndexDuplicate) err = JET_errSuccess; } } if (err >= JET_errSuccess && bCreate) { err = JetCloseTable(session, tableid); if (err >= JET_errSuccess) { hr = SetupIndexDataAccessor(_pConn,dwStorage, dwPos, lpTableName); } } } if (lpTableName) { *lpTableName = new wchar_t [wcslen(wTable) + 1]; if (!*lpTableName) { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } wcscpy(*lpTableName, wTable); } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // GetIndexData // //*************************************************************************** HRESULT GetIndexData (CSQLConnection *_pConn, JET_SESID session, JET_TABLEID tableid, DWORD dwPos, INDEXDATA &is) { HRESULT hr = WBEM_E_FAILED; CESEConnection *pConn = (CESEConnection *)_pConn; BYTE buff[512]; long lInLen = 0; unsigned long lLen; is.Clear(); JET_ERR err = JET_errSuccess; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_OBJECTID), &is.dObjectId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_PROPERTYID), &is.iPropertyId, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_ARRAYPOS), &is.iArrayPos, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; switch(dwPos) { case SQL_POS_INDEXNUMERIC: case SQL_POS_INDEXREF: lInLen = sizeof(SQL_ID); break; case SQL_POS_INDEXSTRING: lInLen = MAX_STRING_WIDTH; break; case SQL_POS_INDEXREAL: lInLen = sizeof(double); break; } err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_INDEXVALUE), buff, MAX_STRING_WIDTH, &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; if (lLen > 0) { switch(dwPos) { case SQL_POS_INDEXNUMERIC: case SQL_POS_INDEXREF: is.dValue = *((SQL_ID *)buff); break; case SQL_POS_INDEXSTRING: is.sValue = SysAllocString((LPWSTR)buff); if (!is.sValue) { hr = WBEM_E_OUT_OF_MEMORY; goto exit; } break; case SQL_POS_INDEXREAL: is.rValue = *((double *)buff); break; default: break; // don't set anything - the caller doesn't want this data. } } hr = WBEM_S_NO_ERROR; exit: return hr; } //*************************************************************************** // // GetFirst_IndexData // //*************************************************************************** HRESULT GetFirst_IndexData (CSQLConnection *_pConn, SQL_ID dObjectId, INDEXDATA &cd, JET_TABLEID &tableid, DWORD dwPos) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. JET_SESID session = pConn->GetSessionID(); JET_ERR err = JetSetCurrentIndex(session, tableid, "ObjectId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dObjectId, sizeof(SQL_ID), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dObjectId, sizeof(SQL_ID), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetIndexData(pConn, session, tableid, dwPos, cd); } } } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // GetFirst_IndexDataByProperty // //*************************************************************************** HRESULT GetFirst_IndexDataByProperty (CSQLConnection *_pConn, SQL_ID PropertyId, INDEXDATA &cd, JET_TABLEID tableid, DWORD dwPos) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. JET_SESID session = pConn->GetSessionID(); JET_ERR err = JetSetCurrentIndex(session, tableid, "PropertyId_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &PropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &PropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetIndexData(pConn, session, tableid, dwPos, cd); } } } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // OpenEnum_IndexDataNumeric // //*************************************************************************** HRESULT OpenEnum_IndexDataNumeric (CSQLConnection *_pConn, SQL_ID dStartAt, INDEXDATA &cd, JET_TABLEID &tableid, DWORD &dwPos) { HRESULT hr = WBEM_E_NOT_FOUND; LPWSTR lpTableName; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this value and bind the data. hr = SetupIndexDataAccessor(pConn, WMIDB_STORAGE_NUMERIC, dwPos, &lpTableName); if (SUCCEEDED(hr)) { CDeleteMe d(lpTableName); JET_SESID session = pConn->GetSessionID(); tableid = pConn->GetTableID(lpTableName); JET_ERR err = JetSetCurrentIndex(session, tableid, "IndexValue_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dStartAt, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekGE ); if (err == JET_errSuccess) { hr = GetIndexData(pConn, session, tableid, dwPos, cd); } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_IndexDataNumeric // //*************************************************************************** HRESULT GetFirst_IndexDataNumeric (CSQLConnection *_pConn, SQL_ID dNumericValue, INDEXDATA &cd, JET_TABLEID &tableid, DWORD &dwPos) { HRESULT hr = WBEM_E_NOT_FOUND; LPWSTR lpTableName; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this value and bind the data. hr = SetupIndexDataAccessor(pConn, WMIDB_STORAGE_NUMERIC, dwPos, &lpTableName); if (SUCCEEDED(hr)) { CDeleteMe d(lpTableName); JET_SESID session = pConn->GetSessionID(); tableid = pConn->GetTableID(lpTableName); JET_ERR err = JetSetCurrentIndex(session, tableid, "IndexValue_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dNumericValue, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dNumericValue, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetIndexData(pConn, session, tableid, dwPos, cd); } } } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // OpenEnum_IndexDataString // //*************************************************************************** HRESULT OpenEnum_IndexDataString (CSQLConnection *_pConn, LPWSTR lpStartAt, INDEXDATA &cd, JET_TABLEID &tableid, DWORD &dwPos) { HRESULT hr = WBEM_E_NOT_FOUND; LPWSTR lpTableName; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this value and bind the data. hr = SetupIndexDataAccessor(pConn, WMIDB_STORAGE_STRING, dwPos, &lpTableName); if (SUCCEEDED(hr)) { CDeleteMe d(lpTableName); JET_SESID session = pConn->GetSessionID(); tableid = pConn->GetTableID(lpTableName); JET_ERR err = JetSetCurrentIndex(session, tableid, "IndexValue_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, lpStartAt, wcslen(lpStartAt)*2+2, JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekGE ); if (err == JET_errSuccess) { hr = GetIndexData(pConn, session, tableid, dwPos, cd); } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_IndexDataString // //*************************************************************************** HRESULT GetFirst_IndexDataString (CSQLConnection *_pConn, LPWSTR lpStringValue, INDEXDATA &cd, JET_TABLEID &tableid, DWORD &dwPos) { HRESULT hr = WBEM_E_NOT_FOUND; LPWSTR lpTableName; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this value and bind the data. hr = SetupIndexDataAccessor(pConn, WMIDB_STORAGE_STRING, dwPos, &lpTableName); if (SUCCEEDED(hr)) { CDeleteMe d(lpTableName); JET_SESID session = pConn->GetSessionID(); tableid = pConn->GetTableID(lpTableName); JET_ERR err = JetSetCurrentIndex(session, tableid, "IndexValue_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, lpStringValue, wcslen(lpStringValue)*2+2, JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, lpStringValue, wcslen(lpStringValue)*2+2, JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { if (err == JET_errSuccess) hr = GetIndexData(pConn, session, tableid, dwPos, cd); } } } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // OpenEnum_IndexDataReal // //*************************************************************************** HRESULT OpenEnum_IndexDataReal (CSQLConnection *_pConn, double dStartAt, INDEXDATA &cd, JET_TABLEID &tableid, DWORD &dwPos) { HRESULT hr = WBEM_E_NOT_FOUND; LPWSTR lpTableName; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this value and bind the data. hr = SetupIndexDataAccessor(pConn, WMIDB_STORAGE_REAL, dwPos, &lpTableName); if (SUCCEEDED(hr)) { CDeleteMe d(lpTableName); JET_SESID session = pConn->GetSessionID(); tableid = pConn->GetTableID(lpTableName); JET_ERR err = JetSetCurrentIndex(session, tableid, "IndexValue_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dStartAt, sizeof(double), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekGE ); if (err == JET_errSuccess) { hr = GetIndexData(pConn, session, tableid, dwPos, cd); } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_IndexDataReal // //*************************************************************************** HRESULT GetFirst_IndexDataReal (CSQLConnection *_pConn, double dValue, INDEXDATA &cd, JET_TABLEID &tableid, DWORD &dwPos) { HRESULT hr = WBEM_E_NOT_FOUND; LPWSTR lpTableName; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this value and bind the data. hr = SetupIndexDataAccessor(pConn, WMIDB_STORAGE_REAL, dwPos, &lpTableName); if (SUCCEEDED(hr)) { CDeleteMe d(lpTableName); JET_SESID session = pConn->GetSessionID(); tableid = pConn->GetTableID(lpTableName); JET_ERR err = JetSetCurrentIndex(session, tableid, "IndexValue_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dValue, sizeof(double), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dValue, sizeof(double), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetIndexData(pConn, session, tableid, dwPos, cd); } } } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // OpenEnum_IndexDataRef // //*************************************************************************** HRESULT OpenEnum_IndexDataRef (CSQLConnection *_pConn, SQL_ID dStartAt, INDEXDATA &cd, JET_TABLEID &tableid, DWORD &dwPos) { HRESULT hr = WBEM_E_NOT_FOUND; LPWSTR lpTableName; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this value and bind the data. hr = SetupIndexDataAccessor(pConn, WMIDB_STORAGE_REFERENCE, dwPos, &lpTableName); if (SUCCEEDED(hr)) { CDeleteMe d(lpTableName); JET_SESID session = pConn->GetSessionID(); tableid = pConn->GetTableID(lpTableName); JET_ERR err = JetSetCurrentIndex(session, tableid, "IndexValue_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dStartAt, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekGE ); if (err == JET_errSuccess) { hr = GetIndexData(pConn, session, tableid, dwPos, cd); } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetFirst_IndexDataRef // //*************************************************************************** HRESULT GetFirst_IndexDataRef (CSQLConnection *_pConn, SQL_ID dValue, INDEXDATA &cd, JET_TABLEID &tableid, DWORD &dwPos) { HRESULT hr = WBEM_E_NOT_FOUND; LPWSTR lpTableName; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this value and bind the data. hr = SetupIndexDataAccessor(pConn, WMIDB_STORAGE_REFERENCE, dwPos, &lpTableName); if (SUCCEEDED(hr)) { CDeleteMe d(lpTableName); JET_SESID session = pConn->GetSessionID(); tableid = pConn->GetTableID(lpTableName); JET_ERR err = JetSetCurrentIndex(session, tableid, "IndexValue_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dValue, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dValue, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { if (err == JET_errSuccess) hr = GetIndexData(pConn, session, tableid, dwPos, cd); } } } } } if (err != JET_errSuccess) hr = WBEM_E_NOT_FOUND; } return hr; } //*************************************************************************** // // GetNext_IndexData // //*************************************************************************** HRESULT GetNext_IndexData (CSQLConnection *_pConn, JET_TABLEID tableid, DWORD dwPos, INDEXDATA &cd) { HRESULT hr = 0; cd.Clear(); JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; JET_SESID session = pConn->GetSessionID(); err = JetMove(session, tableid, JET_MoveNext, 0); if (err == JET_errSuccess) hr = GetIndexData(pConn, session, tableid, dwPos, cd); else hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // UpdateIndexData // //*************************************************************************** HRESULT UpdateIndexData (CSQLConnection *_pConn, INDEXDATA is, LPWSTR lpTableName, DWORD dwStorage, BOOL bDelete = FALSE) { HRESULT hr = WBEM_S_NO_ERROR; JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(lpTableName); unsigned long lLen; err = JetSetCurrentIndex(session, tableid, "ObjectId_idx"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &is.dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &is.dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); while (err == JET_errSuccess) { INDEXDATA is2; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_ARRAYPOS), &is2.iArrayPos, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_PROPERTYID), &is2.iPropertyId, sizeof(DWORD), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto Exit; if (is.iPropertyId == is2.iPropertyId && is.iArrayPos == is2.iArrayPos) { err = JetPrepareUpdate(session, tableid, JET_prepReplace); if (err == JET_errSuccess) { switch(dwStorage) { case WMIDB_STORAGE_STRING: err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_INDEXVALUE), is.sValue, wcslen(is.sValue)*2+2, 0, NULL); break; case WMIDB_STORAGE_NUMERIC: case WMIDB_STORAGE_REFERENCE: err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_INDEXVALUE), &is.dValue, sizeof(SQL_ID), 0, NULL); break; case WMIDB_STORAGE_REAL: err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_INDEXVALUE), &is.rValue, sizeof(SQL_ID), 0, NULL); break; } if (bDelete) err = JetDelete(session, tableid); else err = JetUpdate(session, tableid, NULL, 0, NULL ); } break; } else err = JetMove(session, tableid, JET_MoveNext, 0); } } } } } Exit: hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // InsertIndexData // //*************************************************************************** HRESULT InsertIndexData (CSQLConnection *_pConn, SQL_ID dObjectId, DWORD iPropID, DWORD iArrayPos, LPWSTR lpValue, SQL_ID dValue, double rValue, DWORD dwStorage) { HRESULT hr = 0; DWORD dwPos = 0; LPWSTR lpTableName = NULL; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = 0; hr = SetupIndexDataAccessor(pConn, dwStorage, dwPos, &lpTableName); if (SUCCEEDED(hr)) { if (dwStorage == WMIDB_STORAGE_IMAGE || !lpTableName) return 0; CDeleteMe d (lpTableName); INDEXDATA is; is.dObjectId = dObjectId; is.iPropertyId = iPropID; is.iArrayPos = iArrayPos; is.sValue = SysAllocString(lpValue); if (lpValue && !is.sValue) { hr = WBEM_E_OUT_OF_MEMORY; goto Exit; } is.dValue = dValue; is.rValue = rValue; if (FAILED(UpdateIndexData(pConn, is, lpTableName, dwStorage))) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(lpTableName); err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_OBJECTID), &dObjectId, sizeof(__int64), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_ARRAYPOS), &iArrayPos, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_PROPERTYID), &iPropID, sizeof(DWORD), 0, NULL); if (err < JET_errSuccess) goto Exit; switch(dwStorage) { case WMIDB_STORAGE_STRING: err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_INDEXVALUE), lpValue, wcslen(lpValue)*2+2, 0, NULL); break; case WMIDB_STORAGE_NUMERIC: case WMIDB_STORAGE_REFERENCE: err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_INDEXVALUE), &dValue, sizeof(SQL_ID), 0, NULL); break; case WMIDB_STORAGE_REAL: err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, INDEXTBL_COL_INDEXVALUE), &rValue, sizeof(double), 0, NULL); break; } if (err < JET_errSuccess) goto Exit; err = JetUpdate(session, tableid, NULL, 0, NULL ); } } is.Clear(); hr = WBEM_S_NO_ERROR; } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // SetupContainerObjsAccessor // //*************************************************************************** HRESULT SetupContainerObjsAccessor (CSQLConnection *_pConn) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = JET_errSuccess; if (!pConn->GetTableID(L"ContainerObjs")) { JET_SESID session; JET_TABLEID tableid; JET_DBID dbid; const LPSTR lpTbl = "ContainerObjs"; BOOL bCreate = FALSE; // Get the session and table ID // and create columns as needed. session = pConn->GetSessionID(); dbid = pConn->GetDBID(); err = JetOpenTable (session, dbid, lpTbl, NULL, 0, JET_bitTableUpdatable, &tableid); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); bCreate = TRUE; err = JetCreateTable(session, dbid, lpTbl, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } else pConn->SetTableID(L"ContainerObjs", tableid); JET_COLUMNID colid; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ContainerId", CONTAINEROBJS_COL_CONTAINERID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CONTAINEROBJS_COL_CONTAINERID, colid); else goto Exit; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ContaineeId", CONTAINEROBJS_COL_CONTAINEEID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, CONTAINEROBJS_COL_CONTAINEEID, colid); else goto Exit; err = JetCreateIndex(session, tableid, "ContainerObjs_PK", JET_bitIndexDisallowNull,"+ContainerId\0", 14, 100); if (err >= JET_errSuccess || JET_errIndexDuplicate == err) { err = JetCreateIndex(session, tableid, "Containee_idx", JET_bitIndexDisallowNull ,"+ContaineeId\0", 14, 100); if (err == JET_errIndexDuplicate) err = JET_errSuccess; } if (err >= JET_errSuccess && bCreate) { err = JetCloseTable(session, tableid); if (err >= JET_errSuccess) { hr = SetupContainerObjsAccessor(_pConn); } } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // GetContainerObjsData // //*************************************************************************** HRESULT GetContainerObjsData (CSQLConnection *_pConn, JET_SESID session, JET_TABLEID tableid, CONTAINEROBJ &co) { HRESULT hr = WBEM_E_FAILED; JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; unsigned long lLen; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CONTAINEROBJS_COL_CONTAINERID), &co.dContainerId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, CONTAINEROBJS_COL_CONTAINEEID), &co.dContaineeId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); if (JET_errSuccess > err) goto exit; hr = WBEM_S_NO_ERROR; exit: return hr; } //*************************************************************************** // // GetFirst_ContainerObjs // //*************************************************************************** HRESULT GetFirst_ContainerObjs (CSQLConnection *_pConn, SQL_ID dContainerId, CONTAINEROBJ &cd) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupContainerObjsAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ContainerObjs"); // Use the default index // Grab the first row, // and stuff it into the OBJECTMAP object. JET_ERR err = JetSetCurrentIndex(session, tableid, "ContainerObjs_PK"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dContainerId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dContainerId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { hr = GetContainerObjsData(pConn, session, tableid, cd); } } } } } hr = CSQLExecute::GetWMIError(err); } return hr; } //*************************************************************************** // // GetFirst_ContainerObjsByContainee // //*************************************************************************** HRESULT GetFirst_ContainerObjsByContainee (CSQLConnection *_pConn, SQL_ID dContaineeId, CONTAINEROBJ &cd) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupContainerObjsAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ContainerObjs"); // Use the default index // Grab the first row, // and stuff it into the OBJECTMAP object. JET_ERR err = JetSetCurrentIndex(session, tableid, "Containee_idx"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dContaineeId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &dContaineeId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); if (err == JET_errSuccess) { if (err == JET_errSuccess) hr = GetContainerObjsData(pConn, session, tableid, cd); } } } } } hr = CSQLExecute::GetWMIError(err); } return hr; } //*************************************************************************** // // GetNext_ContainerObjs // //*************************************************************************** HRESULT GetNext_ContainerObjs (CSQLConnection *_pConn, CONTAINEROBJ &cd) { HRESULT hr = 0; cd.Clear(); JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ContainerObjs"); err = JetMove(session, tableid, JET_MoveNext, 0); if (err == JET_errSuccess) hr = GetContainerObjsData(pConn, session, tableid, cd); else hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // UpdateContainerObjs // //*************************************************************************** HRESULT UpdateContainerObjs (CSQLConnection *_pConn, CONTAINEROBJ co, BOOL bDelete = FALSE) { HRESULT hr = WBEM_S_NO_ERROR; JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; if (!bDelete) return 0; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ContainerObjs"); err = JetSetCurrentIndex(session, tableid, "ContainerObjs_PK"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &co.dContainerId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &co.dContainerId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeInclusive|JET_bitRangeUpperLimit); while (err == JET_errSuccess) { CONTAINEROBJ co2; hr = GetContainerObjsData(pConn, session, tableid, co2); if (co.dContainerId == co2.dContainerId && co.dContaineeId == co2.dContaineeId) { err = JetDelete(session, tableid); break; } err = JetMove(session, tableid, JET_MoveNext, 0); } } } } } hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // InsertContainerObjs // //*************************************************************************** HRESULT InsertContainerObjs(CSQLConnection *pConn2, SQL_ID dContainerId, SQL_ID dContaineeId) { HRESULT hr = 0; JET_ERR err = 0; CESEConnection *pConn = (CESEConnection *)pConn2; hr = SetupContainerObjsAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"ContainerObjs"); BOOL bFound = FALSE; CONTAINEROBJ co; hr = GetFirst_ContainerObjs(pConn2, dContainerId, co); while (SUCCEEDED(hr)) { if (co.dContainerId == dContainerId && co.dContaineeId == dContaineeId) { bFound = TRUE; break; } hr = GetNext_ContainerObjs(pConn2, co); } hr = WBEM_S_NO_ERROR; if (!bFound) { err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CONTAINEROBJS_COL_CONTAINERID), &dContainerId, sizeof(__int64), 0, NULL ); if (err < JET_errSuccess) goto Exit; err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, CONTAINEROBJS_COL_CONTAINEEID), &dContaineeId, sizeof(__int64), 0, NULL ); if (err < JET_errSuccess) goto Exit; err = JetUpdate(session, tableid, NULL, 0, NULL ); hr = WBEM_S_NO_ERROR; } } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // SetupAutoDeleteAccessor // //*************************************************************************** HRESULT SetupAutoDeleteAccessor(CSQLConnection *_pConn) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = JET_errSuccess; if (!pConn->GetTableID(L"AutoDelete")) { JET_SESID session; JET_TABLEID tableid; JET_DBID dbid; const LPSTR lpTbl = "AutoDelete"; BOOL bCreate = FALSE; // Get the session and table ID // and create columns as needed. session = pConn->GetSessionID(); dbid = pConn->GetDBID(); err = JetOpenTable (session, dbid, lpTbl, NULL, 0, JET_bitTableUpdatable, &tableid); if (err < JET_errSuccess) { CSQLExecute::GetWMIError(err); bCreate = TRUE; err = JetCreateTable(session, dbid, lpTbl, 10, 80, &tableid); if (err < JET_errSuccess) { hr = CSQLExecute::GetWMIError(err); goto Exit; } } else pConn->SetTableID(L"AutoDelete", tableid); JET_COLUMNID colid; hr = AddColumnToTable(pConn, tableid, lpTbl, L"ObjectId", CONTAINEROBJS_COL_CONTAINERID, JET_coltypCurrency, JET_bitColumnNotNULL, sizeof(SQL_ID), &colid); if (SUCCEEDED(hr)) pConn->SetColumnID(tableid, AUTODELETE_COL_OBJECTID, colid); else goto Exit; err = JetCreateIndex(session, tableid, "AutoDelete_PK", JET_bitIndexPrimary | JET_bitIndexUnique,"+ObjectId\0", 11, 100); if (err >= JET_errSuccess || JET_errIndexHasPrimary == err) err = JET_errSuccess; if (err >= JET_errSuccess && bCreate) { err = JetCloseTable(session, tableid); if (err >= JET_errSuccess) { hr = SetupAutoDeleteAccessor(_pConn); } } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // OpenEnum_AutoDelete // //*************************************************************************** HRESULT OpenEnum_AutoDelete (CSQLConnection *_pConn, AUTODELETE &ad) { HRESULT hr = WBEM_E_NOT_FOUND; // Locate the first row for this ObjectID and bind the data. CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupAutoDeleteAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"AutoDelete"); JET_ERR err = JetSetCurrentIndex(session, tableid, "AutoDelete_PK"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMove(session, tableid, JET_MoveFirst, 0); if (err == JET_errSuccess) { ULONG lLen; err = JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, AUTODELETE_COL_OBJECTID), &ad.dObjectId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL); } } hr = CSQLExecute::GetWMIError(err); } return hr; } //*************************************************************************** // // GetNext_AutoDelete // //*************************************************************************** HRESULT GetNext_AutoDelete(CSQLConnection *_pConn, AUTODELETE &ad) { HRESULT hr = 0; JET_ERR err = JET_errSuccess; CESEConnection *pConn = (CESEConnection *)_pConn; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"AutoDelete"); err = JetMove(session, tableid, JET_MoveNext, 0); if (err == JET_errSuccess) { ULONG lLen; hr = CSQLExecute::GetWMIError(JetRetrieveColumn(session, tableid, pConn->GetColumnID(tableid, AUTODELETE_COL_OBJECTID), &ad.dObjectId, sizeof(SQL_ID), &lLen, JET_bitRetrieveCopy, NULL)); } else hr = WBEM_E_NOT_FOUND; return hr; } //*************************************************************************** // // InsertAutoDelete // //*************************************************************************** HRESULT InsertAutoDelete(CSQLConnection *_pConn, SQL_ID dObjectId) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; JET_ERR err = 0; hr = SetupAutoDeleteAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"AutoDelete"); hr = DeleteAutoDelete(pConn, dObjectId); err = JetPrepareUpdate(session, tableid, JET_prepInsert); if (err == JET_errSuccess) { err = JetSetColumn(session, tableid, pConn->GetColumnID(tableid, AUTODELETE_COL_OBJECTID), &dObjectId, sizeof(__int64), 0, NULL ); if (err < JET_errSuccess) goto Exit; err = JetUpdate(session, tableid, NULL, 0, NULL ); hr = WBEM_S_NO_ERROR; } } Exit: if (err) hr = CSQLExecute::GetWMIError(err); return hr; } //*************************************************************************** // // DeleteAutoDelete // //*************************************************************************** HRESULT DeleteAutoDelete(CSQLConnection *_pConn, SQL_ID dObjectId) { HRESULT hr = WBEM_E_NOT_FOUND; CESEConnection *pConn = (CESEConnection *)_pConn; // Locate the first row for this ObjectID and bind the data. hr = SetupAutoDeleteAccessor(pConn); if (SUCCEEDED(hr)) { JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"AutoDelete"); JET_ERR err = JetSetCurrentIndex(session, tableid, "AutoDelete_PK"); if (err == JET_errSuccess) { err = JetSetIndexRange(session, tableid, JET_bitRangeRemove); err = JetMakeKey(session, tableid, &dObjectId, sizeof(__int64), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetDelete(session, tableid); } } } hr = CSQLExecute::GetWMIError(err); if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; } return hr; } //*************************************************************************** // // CleanAutoDeletes // //*************************************************************************** HRESULT CleanAutoDeletes(CSQLConnection *pConn) { HRESULT hr; AUTODELETE ad; SQLIDs ids; // These are objects created with the AUTODELETE handle. // If we have any left, we must have crashed before // the handles could be tidied up. hr = OpenEnum_AutoDelete(pConn, ad); while (SUCCEEDED(hr)) { ids.push_back(ad.dObjectId); hr = GetNext_AutoDelete(pConn, ad); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; if (SUCCEEDED(hr)) { for (int i = 0; i < ids.size(); i++) { hr = DeleteObjectMap(pConn, ids.at(i)); if (FAILED(hr)) break; } } return hr; } // Delete functions //*************************************************************************** // // DeleteIndexDataByObjectId // //*************************************************************************** HRESULT DeleteIndexDataByObjectId (CSQLConnection *_pConn, DWORD dwStorage, SQL_ID dObjectId) { HRESULT hr = 0; LPWSTR lpTableName = NULL; DWORD dwPos = 0; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupIndexDataAccessor(pConn, dwStorage, dwPos, &lpTableName); if (SUCCEEDED(hr)) { CDeleteMe d (lpTableName); if (!lpTableName || dwStorage == WMIDB_STORAGE_IMAGE) return 0; INDEXDATA is; JET_TABLEID tableid = pConn->GetTableID(lpTableName); hr = GetFirst_IndexData(pConn, dObjectId, is, tableid, dwPos); while (SUCCEEDED(hr)) { hr = UpdateIndexData(pConn, is, lpTableName, dwStorage, TRUE); if (FAILED(hr)) { is.Clear(); break; } hr = GetNext_IndexData(pConn, tableid, dwPos, is); if (hr == WBEM_E_NOT_FOUND) { hr = WBEM_S_NO_ERROR; break; } if (is.dObjectId != dObjectId) break; } hr = WBEM_S_NO_ERROR; } return hr; } //*************************************************************************** // // DeletePropertyMap // //*************************************************************************** HRESULT DeletePropertyMap (CSQLConnection *_pConn, DWORD iPropertyId) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; PROPERTYMAP pm; hr = GetFirst_PropertyMap(pConn, iPropertyId, pm); if (SUCCEEDED(hr)) { hr = DeleteReferenceProperties(_pConn, iPropertyId); if (SUCCEEDED(hr)) hr = UpdatePropertyMap(pConn, pm, TRUE); } else hr = WBEM_S_NO_ERROR; return hr; } //*************************************************************************** // // DeleteClassData // //*************************************************************************** HRESULT DeleteClassData (CSQLConnection *_pConn, DWORD iPropertyId, SQL_ID dObjectId=0, DWORD iArrayPos = -1) { HRESULT hr = 0; CLASSDATA cd; CESEConnection *pConn = (CESEConnection *)_pConn; hr = GetFirst_ClassDataByPropertyId(pConn, iPropertyId, cd); while (SUCCEEDED(hr)) { BOOL bMatch = TRUE; if (dObjectId && dObjectId != cd.dObjectId) bMatch = FALSE; if ((int)iArrayPos >= 0 && iArrayPos != cd.iArrayPos) bMatch = FALSE; if (bMatch) { hr = UpdateClassData_Internal(pConn, cd, TRUE); if (FAILED(hr)) { cd.Clear(); break; } } hr = GetNext_ClassData(pConn, cd); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; return hr; } //*************************************************************************** // // DeleteClassImages // //*************************************************************************** HRESULT DeleteClassImages (CSQLConnection *_pConn, DWORD iPropertyId, SQL_ID dObjectId=0, DWORD iArrayPos = -1) { HRESULT hr = 0; CLASSIMAGES cd; CESEConnection *pConn = (CESEConnection *)_pConn; hr = GetFirst_ClassImagesByPropertyId(pConn, iPropertyId, cd); while (SUCCEEDED(hr)) { BOOL bMatch = TRUE; if (dObjectId && dObjectId != cd.dObjectId) bMatch = FALSE; if (iArrayPos != -1 && iArrayPos != cd.iArrayPos) bMatch = FALSE; if (bMatch) { hr = UpdateClassImages(pConn, cd, TRUE); if (FAILED(hr)) { cd.Clear(); break; } } hr = GetNext_ClassImages(pConn, cd); if (cd.iPropertyId != iPropertyId) break; } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; return hr; } //*************************************************************************** // // DeleteContainerObjs // //*************************************************************************** HRESULT DeleteContainerObjs (CSQLConnection *_pConn, SQL_ID dContainerId, SQL_ID dContaineeId ) { HRESULT hr = 0; CONTAINEROBJ co; CESEConnection *pConn = (CESEConnection *)_pConn; if (dContainerId) hr = GetFirst_ContainerObjs (pConn, dContainerId, co); else hr = GetFirst_ContainerObjsByContainee (pConn, dContaineeId, co); while (SUCCEEDED(hr)) { BOOL bMatch = TRUE; if (dContainerId && co.dContainerId != dContainerId) bMatch = FALSE; if (dContaineeId && co.dContaineeId != dContaineeId) bMatch = FALSE; if (bMatch) hr = UpdateContainerObjs (pConn, co, TRUE); hr = GetNext_ContainerObjs(pConn, co); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; return hr; } //*************************************************************************** // // DeleteQualifiers // //*************************************************************************** HRESULT DeleteQualifiers (CSQLConnection *_pConn, SQL_ID dObjectId) { HRESULT hr = 0; CLASSDATA cd; CESEConnection *pConn = (CESEConnection *)_pConn; hr = GetFirst_ClassData (pConn, dObjectId, cd); while (SUCCEEDED(hr)) { // Delete any properties with the qualifier flag set. if (cd.iFlags & 2) { hr = UpdateClassData_Internal(pConn, cd, TRUE); if (FAILED(hr)) { cd.Clear(); goto Exit; } } hr = GetNext_ClassData(pConn, cd); if (cd.dObjectId != dObjectId) break; } hr = WBEM_S_NO_ERROR; Exit: return hr; } //*************************************************************************** // // DeletePropQualifiers // //*************************************************************************** HRESULT DeletePropQualifiers (CSQLConnection *_pConn, DWORD iPropertyId) { HRESULT hr = 0; CLASSDATA cd; CESEConnection *pConn = (CESEConnection *)_pConn; hr = GetFirst_ClassDataByRefId (pConn, ((SQL_ID)iPropertyId), cd); while (SUCCEEDED(hr)) { // Delete any properties with the qualifier flag set. if (cd.iFlags & 2) { hr = UpdateClassData_Internal(pConn, cd, TRUE); if (FAILED(hr)) { cd.Clear(); goto Exit; } } hr = GetNext_ClassData(pConn, cd); if (cd.iPropertyId != iPropertyId) break; } hr = WBEM_S_NO_ERROR; Exit: return hr; } //*************************************************************************** // // DeleteIndexData // //*************************************************************************** HRESULT DeleteIndexData (CSQLConnection *_pConn, DWORD dwStorage, DWORD iPropertyId, SQL_ID dObjectId=0, DWORD iArrayPos = -1) { HRESULT hr = 0; LPWSTR lpTableName = NULL; DWORD dwPos = 0; CESEConnection *pConn = (CESEConnection *)_pConn; hr = SetupIndexDataAccessor(pConn, dwStorage, dwPos, &lpTableName); if (SUCCEEDED(hr)) { CDeleteMe d (lpTableName); if (!lpTableName || dwStorage == WMIDB_STORAGE_IMAGE) return 0; INDEXDATA is; JET_TABLEID tableid = pConn->GetTableID(lpTableName); hr = GetFirst_IndexDataByProperty(pConn, iPropertyId, is, tableid, dwPos); while (SUCCEEDED(hr)) { BOOL bMatch = TRUE; if (dObjectId && is.dObjectId != dObjectId) bMatch = FALSE; if (iArrayPos != -1 && iArrayPos != is.iArrayPos) bMatch = FALSE; if (bMatch) { hr = UpdateIndexData(pConn, is, lpTableName, dwStorage, TRUE); if (FAILED(hr)) { is.Clear(); break; } } hr = GetNext_IndexData(pConn, tableid, dwPos, is); if (hr == WBEM_E_NOT_FOUND) { hr = WBEM_S_NO_ERROR; break; } if (iPropertyId != is.iPropertyId) break; } hr = WBEM_S_NO_ERROR; } return hr; } //*************************************************************************** // // DeleteObjectMap // //*************************************************************************** HRESULT DeleteObjectMap (CSQLConnection *_pConn, SQL_ID dObjectId, BOOL bDecRef, SQL_ID dScope) { HRESULT hr = 0; CESEConnection *pConn = (CESEConnection *)_pConn; // Set up the maximum ref count that can exist // to physically delete the object. int iMaxRef = 0; if (bDecRef) iMaxRef = 1; OBJECTMAP oj; int i; BOOL bDelete = FALSE; hr = GetFirst_ObjectMap(pConn, dObjectId, oj); if (SUCCEEDED(hr)) { DEBUGTRACE((LOG_WBEMCORE, "DeleteObjectMap %S (RefCount = %ld)\n", oj.sObjectPath, oj.iRefCount)); // If we are calling this internally, // we need to determine if this is an embedded object // or a reference. If an embedded object, // always delete it. If a reference, only delete // if its in a deleted state, and ref count = 0 // Otherwise, decrement its ref count. if (dScope) { if (oj.dObjectScopeId == dScope) { bDelete = TRUE; } else { if (bDecRef) { if (oj.iRefCount > 0) oj.iRefCount--; } if (oj.iObjectState == 2 && !oj.iRefCount) { bDelete = TRUE; } } } else { if (oj.iRefCount <= iMaxRef) { bDelete = TRUE; } else { if (bDecRef) oj.iRefCount--; oj.iObjectState = 2; } } // wprintf(L">> Deleting %I64d (%s) \n", dObjectId, (LPWSTR)oj.sObjectKey); if (bDelete) { // Delete from the INDEX tables... hr = DeleteIndexDataByObjectId(pConn, WMIDB_STORAGE_STRING, dObjectId); if (FAILED(hr)) goto Exit; hr = DeleteIndexDataByObjectId(pConn, WMIDB_STORAGE_NUMERIC, dObjectId); if (FAILED(hr)) goto Exit; hr = DeleteIndexDataByObjectId(pConn, WMIDB_STORAGE_REAL, dObjectId); if (FAILED(hr)) goto Exit; hr = DeleteIndexDataByObjectId(pConn, WMIDB_STORAGE_REFERENCE, dObjectId); if (FAILED(hr)) goto Exit; // If this was an autodelete handle, kill it. hr = DeleteAutoDelete(pConn, dObjectId); if (FAILED(hr)) goto Exit; hr = DeleteReferencePropertiesByClass(pConn, dObjectId); if (FAILED(hr)) goto Exit; hr = DeleteScopeMap(pConn, dObjectId); if (FAILED(hr)) goto Exit; // DELETE CLASSDATA AND CLASSIMAGES SQLIDs ids; CLASSDATA cd; hr = GetFirst_ClassData(pConn, dObjectId, cd); while (SUCCEEDED(hr)) { // If this is a reference or an embedded object, // decrement ref counts or delete if (cd.dRefId) ids.push_back(cd.dRefId); hr = UpdateClassData_Internal(pConn, cd, TRUE); if (FAILED(hr)) { cd.Clear(); break; } hr = GetNext_ClassData(pConn, cd); if (cd.dObjectId != dObjectId) { cd.Clear(); break; } } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; if (FAILED(hr)) goto Exit; CLASSIMAGES ci; hr = GetFirst_ClassImages(pConn, dObjectId, ci); while (SUCCEEDED(hr)) { hr = UpdateClassImages(pConn, ci, TRUE); if (FAILED(hr)) { ci.Clear(); break; } hr = GetNext_ClassImages(pConn, ci); if (ci.dObjectId != dObjectId) break; } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; if (FAILED(hr)) goto Exit; // If this is a class, delete CLASSMAP AND PROPERTYMAP if (oj.dClassId == 1) { PROPERTYMAP pm; hr = GetFirst_PropertyMapByClass(pConn, dObjectId, pm); while (SUCCEEDED(hr)) { hr = UpdatePropertyMap(pConn, pm, TRUE); if (FAILED(hr)) { pm.Clear(); goto Exit; } hr = GetNext_PropertyMap(pConn, pm); if (dObjectId != pm.dClassId) break; } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; if (FAILED(hr)) goto Exit; hr = DeleteClassKeys(pConn, dObjectId); CLASSMAP cm; hr = GetFirst_ClassMap(pConn, dObjectId, cm); if (SUCCEEDED(hr)) hr = UpdateClassMap(pConn, cm, TRUE); cm.Clear(); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; if (FAILED(hr)) goto Exit; // Remove container memberships hr = DeleteContainerObjs (pConn, dObjectId, 0); if (SUCCEEDED(hr)) hr = DeleteContainerObjs (pConn, 0, dObjectId); // Delete or decrement ref counts on // references and embedded objects for (i = 0; i < ids.size(); i++) { hr = DeleteObjectMap(_pConn, ids.at(i), TRUE, dObjectId); if (FAILED(hr)) goto Exit; } // FINALLY, delete from ObjectMap. if (SUCCEEDED(hr)) hr = UpdateObjectMap(pConn, oj, TRUE); } // Otherwise, set the state of this object to "Deleted" // and leave it in the tables. else hr = UpdateObjectMap(pConn, oj); oj.Clear(); } else hr = WBEM_S_NO_ERROR; Exit: oj.Clear(); return hr; } //*************************************************************************** // // CWmiDbSession::Delete // //*************************************************************************** HRESULT CWmiDbSession::Delete(IWmiDbHandle *pHandle, CSQLConnection *pConn) { HRESULT hr = WBEM_S_NO_ERROR; DWORD dwNumRows = 0; CWmiDbHandle *pTmp = (CWmiDbHandle *)pHandle; bool bLocalTrans = false; if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN; SQL_ID dID = pTmp->m_dObjectId; SQL_ID dClassID = pTmp->m_dClassId; hr = VerifyObjectLock(dID, pTmp->m_dwHandleType, pTmp->m_dwVersion); if (FAILED(hr) && IsDistributed()) { if (LockExists(dID)) hr = WBEM_S_NO_ERROR; } if (SUCCEEDED(hr)) { if (!pConn && m_pController) { bLocalTrans = true; hr = GetSQLCache()->GetConnection(&pConn, TRUE, IsDistributed()); } if (SUCCEEDED(hr)) { hr = Delete(dID, pConn); if (bLocalTrans && m_pController) GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed()); } } return hr; } HRESULT AddToSQLIDs (SQL_ID dID, SQLIDs *pToDel) { HRESULT hr = 0; BOOL bFound = FALSE; for (int i = 0; i < pToDel->size(); i++) { if (pToDel->at(i) == dID) { bFound = TRUE; break; } } if (!bFound) pToDel->push_back(dID); return hr; } HRESULT GetIdsToDelete (SQL_ID dID, CSQLConnection *pConn, SQLIDs *pToDel) { HRESULT hr = 0; OBJECTMAP om; SQLIDs NewList; hr = GetFirst_ObjectMap(pConn, dID, om); if (SUCCEEDED(hr)) { // Decrement ref counts on reference properties. CLASSDATA cd; SQLIDs ToUpd; hr = GetFirst_ClassDataByRefId(pConn, dID, cd); while (hr == WBEM_S_NO_ERROR) { ToUpd.push_back(cd.dObjectId); hr = GetNext_ClassData(pConn, cd); if (cd.dRefId != dID) { cd.Clear(); break; } } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; for (int i = 0; i < ToUpd.size(); i++) { hr = GetFirst_ObjectMap(pConn, ToUpd.at(i), om); if (hr == WBEM_S_NO_ERROR) { if (om.iRefCount > 0) om.iRefCount--; hr = UpdateObjectMap(pConn, om); om.Clear(); } } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; hr = GetFirst_ObjectMapByScope(pConn, dID, om); while (hr == WBEM_S_NO_ERROR) { SQL_ID dSubId = om.dObjectId; AddToSQLIDs(dSubId, &NewList); hr = GetNext_ObjectMap(pConn, om); if (om.dObjectScopeId != dID) break; } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; // Classes if (SUCCEEDED(hr)) { hr = GetFirst_ObjectMapByClass(pConn, dID, om); while (hr == WBEM_S_NO_ERROR) { SQL_ID dSubId = om.dObjectId; AddToSQLIDs(dSubId, &NewList); hr = GetNext_ObjectMap(pConn, om); if (om.dClassId != dID) { om.Clear(); break; } } } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; // Then all subclasses if (SUCCEEDED(hr)) { CLASSMAP cd; hr = GetFirst_ClassMapBySuperClass(pConn, dID, cd); while (hr == WBEM_S_NO_ERROR) { SQL_ID dSubId = cd.dClassId; AddToSQLIDs(dSubId, &NewList); hr = GetNext_ClassMap(pConn, cd); if (dID != cd.dSuperClassId) { cd.Clear(); break; } } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; } for (int j = 0; j < NewList.size(); j++) { hr = GetIdsToDelete(NewList.at(j), pConn, pToDel); AddToSQLIDs(NewList.at(j), pToDel); } om.Clear(); } return hr; } HRESULT CheckSecurity(SQLIDs *pToDel, CWmiDbSession *pSession, CSQLConnection *pConn) { HRESULT hr = 0; for (int i = 0; i < pToDel->size(); i++) { OBJECTMAP om; hr = GetFirst_ObjectMap(pConn, pToDel->at(i), om); if (SUCCEEDED(hr)) { hr = pSession->VerifyObjectSecurity(pConn, pToDel->at(i), om.dClassId, om.dObjectScopeId, 0, pSession->GetSchemaCache()->GetWriteToken(pToDel->at(i), om.dClassId)); if (FAILED(hr) && hr != WBEM_E_NOT_FOUND) break; om.Clear(); } } return hr; } //*************************************************************************** // // CWmiDbSession::Delete // //*************************************************************************** HRESULT CWmiDbSession::Delete(SQL_ID dID, CSQLConnection *pConn) { HRESULT hr = WBEM_S_NO_ERROR; int iPos = 0, iMax = 100; SQL_ID dClassId = 0, dScopeId = 0, dObjId = 0; DWORD dwNumRows = 0; wchar_t wBuffer1[550], wBuffer2[550]; int iToUpd = 0, iToDel = 0; SQLIDs ToDel; // We need to enumerate every object that is underneath this one // in the hierarchy, and delete them one-by-one. // This function needs to recurse through all children, // remove the data from the tables, fix reference counts, // and clean the caches. If all that worked, we can commit. // =========================================================== hr = GetIdsToDelete(dID, pConn, &ToDel); if (SUCCEEDED(hr)) { AddToSQLIDs(dID, &ToDel); hr = CheckSecurity(&ToDel, this, pConn); if (SUCCEEDED(hr)) { for (int i = 0; i < ToDel.size(); i++) { hr = DeleteObjectMap(pConn, ToDel.at(i)); if (FAILED(hr)) break; GetSchemaCache()->DeleteClass(ToDel.at(i)); CleanCache(ToDel.at(i)); } } } return hr; } //*************************************************************************** // // CWmiDbSession::GetClassObject // //*************************************************************************** HRESULT CWmiDbSession::GetClassObject (CSQLConnection *pConn, SQL_ID dClassId, IWbemClassObject **ppObj) { HRESULT hr = WBEM_S_NO_ERROR; _IWmiObject *pNew = NULL; SQL_ID dParentId = 0; // All we need to do is read the blob from the database. // This should be cached where space allows. CLASSMAP cm; BOOL bNeedToRelease = FALSE; if (!pConn && m_pController) { hr = GetSQLCache()->GetConnection(&pConn, 0, IsDistributed()); bNeedToRelease = TRUE; if (FAILED(hr)) return hr; } if (SUCCEEDED(hr)) { hr = GetFirst_ClassMap(pConn, dClassId, cm); if (SUCCEEDED(hr)) { if (cm.dSuperClassId != 0 && cm.dSuperClassId != 1) { hr = GetObjectCache()->GetObject(cm.dSuperClassId, ppObj); if (FAILED(hr)) hr = GetClassObject(pConn, cm.dSuperClassId, ppObj); if (SUCCEEDED(hr)) { // Merge the class part. _IWmiObject *pObj = (_IWmiObject *)*ppObj; if (pObj) { hr = pObj->Merge (WMIOBJECT_MERGE_FLAG_CLASS, cm.dwBufferLen, cm.pClassBuffer, &pNew); pObj->Release(); if (SUCCEEDED(hr)) *ppObj = pNew; } else hr = WBEM_E_FAILED; } } else { _IWmiObject *pObj = NULL; hr = CoCreateInstance(CLSID_WbemClassObject, NULL, CLSCTX_INPROC_SERVER, IID__IWmiObject, (void **)&pObj); if (SUCCEEDED(hr)) { hr = pObj->Merge(WMIOBJECT_MERGE_FLAG_CLASS, cm.dwBufferLen, cm.pClassBuffer, &pNew); pObj->Release(); if (SUCCEEDED(hr)) *ppObj = pNew; } } cm.Clear(); } } if (bNeedToRelease && pConn && m_pController) { GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed()); } return hr; } //*************************************************************************** // // CWmiDbSession::GetObjectData // //*************************************************************************** HRESULT CWmiDbSession::GetObjectData (CSQLConnection *pConn, SQL_ID dObjectId, SQL_ID dClassId, SQL_ID dScopeId, DWORD dwHandleType, DWORD &dwVersion, IWbemClassObject **ppObj, BOOL bNoDefaults, LPWSTR lpInKey, BOOL bGetSD ) { HRESULT hr = WBEM_S_NO_ERROR; _bstr_t sClassPath; DWORD dwGenus = 1; DWORD dwRows; bool bUsedCache = false; LPWSTR lpKey = NULL; DWORD dwType = 0, dwVer = 0; if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN; // Validate version if this is a versioned handle. // ================================================- try { if (!bNoDefaults) { hr = VerifyObjectLock(dObjectId, dwHandleType, dwVersion); if (FAILED(hr) && IsDistributed()) { if (LockExists(dObjectId)) hr = WBEM_S_NO_ERROR; } } if (SUCCEEDED(hr)) { // Check the object cache to see if this // IWbemClassObject is already loaded. // Never cache an instance of __Instances // ===================================== if (dClassId == INSTANCESCLASSID) hr = WBEM_E_NOT_FOUND; else hr = GetObjectCache()->GetObject(dObjectId, ppObj); if (FAILED(hr)) { // Otherwise, we need to hit the database. // ======================================= VARIANT vTemp; VariantInit(&vTemp); if (dClassId == 1) { dwGenus = 1; dClassId = dObjectId; } else dwGenus = 2; SQL_ID dTemp = 0; // We now have an object path and class ID. // Now we have to instantiate a new IWbemClassObject, // populate all the system properties // ================================================== IWbemClassObject *pClass = NULL; IWbemClassObject *pTemp = NULL; hr = GetObjectCache()->GetObject(dClassId, &pClass); if (SUCCEEDED(hr)) bUsedCache = true; else hr = GetClassObject(pConn, dClassId, &pClass); if (SUCCEEDED(hr)) { if (dwGenus == 2) { if (pClass) pClass->SpawnInstance(0, &pTemp); { if (pTemp) hr = GetSchemaCache()->DecorateWbemObj(m_sMachineName, m_sNamespacePath, dScopeId, pTemp, dClassId); } } else { pTemp = pClass; hr = GetSchemaCache()->DecorateWbemObj(m_sMachineName, m_sNamespacePath, dScopeId, pTemp, dClassId); } // Special case if this is an __Instances container, // We need to instantiate an instance of __Instances, // and plug the class name into the ClassName property. // =================================================== if (dClassId == INSTANCESCLASSID) { _bstr_t sName, sPath; SQL_ID dTemp1, dTemp2; DWORD dwFlags; hr = GetSchemaCache()->GetClassInfo (dObjectId, sPath, dTemp1, dTemp2, dwFlags, &sName); if (SUCCEEDED(hr)) { VARIANT vTemp; VariantInit(&vTemp); vTemp.bstrVal = SysAllocString(sName); vTemp.vt = VT_BSTR; pTemp->Put(L"ClassName", 0, &vTemp, CIM_STRING); VariantClear(&vTemp); *ppObj = pTemp; } else { pTemp->Release(); pTemp = NULL; } } else { if (lpInKey) { hr = GetObjectData2 (pConn, dObjectId, dClassId, dScopeId, pTemp, FALSE, NULL); lpKey = lpInKey; } else hr = GetObjectData2 (pConn, dObjectId, dClassId, dScopeId, pTemp, FALSE, &lpKey); if (dwGenus == 2) { if (!bUsedCache && SUCCEEDED(hr) && !((dwHandleType & 0xF00) == WMIDB_HANDLE_TYPE_NO_CACHE)) { if (lpKey) { LPWSTR lpEqual = wcsrchr(lpKey, L'.'); if (!lpEqual) lpEqual = wcsrchr(lpKey, L'='); if (lpEqual) { LPWSTR lpPath = Macro_CloneLPWSTR(lpKey); if (lpPath) { CDeleteMe d10 (lpPath); int iPos = lpEqual - lpKey; lpPath[iPos] = L'\0'; GetObjectCache()->PutObject(dClassId, 1, dScopeId, lpPath, 1, pClass); } } } } } if (FAILED(hr)) { pTemp->Release(); pTemp = NULL; } *ppObj = pTemp; } if (dwGenus == 2 && pClass) pClass->Release(); } // If all that worked, try and cache this object. // ============================================== if (SUCCEEDED(hr) && ppObj && (dwHandleType & 0xF00) && dClassId != INSTANCESCLASSID) { // This is allowed to fail, since its *just* a cache. if ((dwHandleType & 0xF00) != WMIDB_HANDLE_TYPE_NO_CACHE && lpKey) { bool bCacheType = ((dwHandleType & 0xF00) == WMIDB_HANDLE_TYPE_STRONG_CACHE) ? 1 : 0; GetObjectCache()->PutObject(dObjectId, dClassId, dScopeId, lpKey, bCacheType, *ppObj); } } if (!lpInKey) delete lpKey; } else { // Make sure the decoration is up-to-date. hr = GetSchemaCache()->DecorateWbemObj(m_sMachineName, m_sNamespacePath, dScopeId, *ppObj, dClassId); } // Populate the security descriptor, if requested if (SUCCEEDED(hr) && bGetSD) { BOOL bNeedToRelease = FALSE; if (!pConn && m_pController) { hr = GetSQLCache()->GetConnection(&pConn, 0, FALSE); bNeedToRelease = TRUE; if (FAILED(hr)) { (*ppObj)->Release(); *ppObj = NULL; return hr; } } PNTSECURITY_DESCRIPTOR pSD = NULL; DWORD dwLen = 0; if (SUCCEEDED(CSQLExecProcedure::GetSecurityDescriptor(pConn, dObjectId, &pSD, dwLen, 0))) { ((_IWmiObject *)*ppObj)->WriteProp(L"__SECURITY_DESCRIPTOR", 0, dwLen, dwLen, CIM_UINT8|CIM_FLAG_ARRAY, pSD); delete pSD; } if (bNeedToRelease && pConn && m_pController) { GetSQLCache()->ReleaseConnection(pConn, hr, FALSE); } } } } catch (...) { hr = WBEM_E_SHUTTING_DOWN; } return hr; } //*************************************************************************** // // CWmiDbSession::GetObjectData2 // //*************************************************************************** HRESULT CWmiDbSession::GetObjectData2 (CSQLConnection *pConn, SQL_ID dObjectId, SQL_ID dClassId, SQL_ID dScopeId, IWbemClassObject *pObj, BOOL bNoDefaults, LPWSTR * lpKey) { HRESULT hr = WBEM_S_NO_ERROR; BOOL bNeedToRelease = FALSE; if (!pObj) return WBEM_E_INVALID_PARAMETER; if (!pConn && m_pController) { hr = GetSQLCache()->GetConnection(&pConn, 0, FALSE); bNeedToRelease = TRUE; if (FAILED(hr)) return hr; } if (SUCCEEDED(hr)) { if (lpKey) { OBJECTMAP oj; hr = GetFirst_ObjectMap(pConn, dObjectId, oj); if (SUCCEEDED(hr)) { if (oj.iObjectState == 2) { DEBUGTRACE((LOG_WBEMCORE, "Object %I64d is marked as deleted\n", dObjectId)); oj.Clear(); return WBEM_E_NOT_FOUND; } if (oj.sObjectKey) { LPWSTR lpKey2 = new wchar_t [wcslen(oj.sObjectKey)+1]; if (lpKey2) { wcscpy(lpKey2, oj.sObjectKey); *lpKey = lpKey2; } else hr = WBEM_E_OUT_OF_MEMORY; } else hr = WBEM_E_INVALID_OBJECT; oj.Clear(); } else hr = WBEM_E_NOT_FOUND; } if (FAILED(hr)) goto Exit; if (dClassId != 1 && dClassId != dObjectId) { CLASSDATA cd; DWORD dwRows; BOOL bBigText = FALSE, bObjProp = FALSE; int i = 0; Properties props; typedef std::vector CDs; CDs cds; hr = GetFirst_ClassData(pConn, dObjectId, cd, -1, TRUE, GetSchemaCache()); while (SUCCEEDED(hr) && hr != WBEM_S_NO_MORE_DATA) { SetObjectData(pConn, pObj, this, &((CWmiDbController *)m_pController)->SchemaCache, cd, FALSE, bBigText, &bObjProp, bNoDefaults); if (bObjProp) { CLASSDATA *pCD = new CLASSDATA; *pCD = cd; cds.push_back(pCD); } hr = GetNext_ClassData(pConn, cd, -1, TRUE, GetSchemaCache()); } hr = WBEM_S_NO_ERROR; // The embedded object properties, since there will // be a move next conflict if we try to retrieve them earlier. for (i = 0; i < cds.size(); i++) { CLASSDATA *pCD = cds.at(i); SetObjectData(pConn, pObj, this, &((CWmiDbController *)m_pController)->SchemaCache, *pCD, FALSE, bBigText, NULL, bNoDefaults); pCD->Clear(); delete pCD; } //if (bBigText || GetSchemaCache()->HasImageProp(dClassId)) { // Finally, anything stored as long binary data. DWORD dwSecurity = 0; GetSchemaCache()->GetPropertyID(L"__SECURITY_DESCRIPTOR", 1, 0, REPDRVR_IGNORE_CIMTYPE, dwSecurity); CLASSIMAGES ci; hr = GetFirst_ClassImages(pConn, dObjectId, ci); while (SUCCEEDED(hr)) { if (ci.iPropertyId != dwSecurity) { // Stuff this blob into the object. cd.Copy(ci); SetObjectData(pConn, pObj, this, &((CWmiDbController *)m_pController)->SchemaCache, cd, TRUE, bBigText, NULL, bNoDefaults); cd.Clear(); } hr = GetNext_ClassImages(pConn, ci); if (ci.dObjectId != dObjectId) break; } } hr = WBEM_S_NO_ERROR; } } hr = WBEM_S_NO_ERROR; Exit: if (bNeedToRelease && pConn && m_pController) { GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed()); } return hr; } //*************************************************************************** // // CSQLExecProcedure::GetHierarchy // //*************************************************************************** HRESULT CSQLExecProcedure::GetHierarchy(CSQLConnection *pConn, SQL_ID dClassId) { HRESULT hr = WBEM_S_NO_ERROR; // Not required for Jet. return hr; } //*************************************************************************** // // CSQLExecProcedure::GetNextUnkeyedPath // //*************************************************************************** HRESULT CSQLExecProcedure::GetNextUnkeyedPath(CSQLConnection *pConn, SQL_ID dClassId, _bstr_t &sNewPath) { HRESULT hr = WBEM_S_NO_ERROR; // Generate a GUID for this object, and use this an artificial path. // The format doesn't matter to us internally. GUID guid; LPWSTR lpNewPath; hr = CoCreateGuid(&guid); if (SUCCEEDED(hr)) { hr = UuidToString(&guid, &lpNewPath); if (SUCCEEDED(hr)) sNewPath = lpNewPath; RpcStringFree(&lpNewPath); } return hr; } //*************************************************************************** // // CSQLExecProcedure::GetNextKeyhole // //*************************************************************************** HRESULT CSQLExecProcedure::GetNextKeyhole(CSQLConnection *pConn2, DWORD iPropertyId, SQL_ID &dNewId) { HRESULT hr = WBEM_S_NO_ERROR; CESEConnection *pConn = (CESEConnection *)pConn2; // Here we need to select the largest value plus one currently // in the table for this property ID. // If null, its one. dNewId = 1; JET_SESID session = pConn->GetSessionID(); JET_TABLEID tableid = pConn->GetTableID(L"IndexNumericData"); JET_ERR err = JetSetCurrentIndex(session, tableid, "PropertyId_idx"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMove(session, tableid, JET_MoveLast, 0); if (err == JET_errSuccess) { INDEXDATA is; hr = GetIndexData(pConn, session, tableid, 0, is); dNewId = is.dValue + 1; } } } } else hr = CSQLExecute::GetWMIError(err); if (dNewId == 1) { tableid = pConn->GetTableID(L"IndexStringData"); err = JetSetCurrentIndex(session, tableid, "PropertyId_idx"); if (err == JET_errSuccess) { err = JetMakeKey(session, tableid, &iPropertyId, sizeof(DWORD), JET_bitNewKey); if (err == JET_errSuccess) { err = JetSeek( session, tableid, JET_bitSeekEQ ); if (err == JET_errSuccess) { err = JetMove(session, tableid, JET_MoveLast, 0); if (err == JET_errSuccess) { INDEXDATA is; hr = GetIndexData(pConn, session, tableid, 0, is); dNewId = _wtoi64(is.sValue) + 1; } } } } else hr = CSQLExecute::GetWMIError(err); } return hr; } //*************************************************************************** // // CSQLExecProcedure::GetObjectIdByPath // //*************************************************************************** HRESULT CSQLExecProcedure::GetObjectIdByPath (CSQLConnection *pConn, LPCWSTR lpPath, SQL_ID &dObjectId, SQL_ID &dClassId, SQL_ID *dScopeId, BOOL *bDeleted) { HRESULT hr = WBEM_S_NO_ERROR; if (!pConn) return WBEM_E_INVALID_PARAMETER; if (!dObjectId && lpPath) dObjectId = CRC64::GenerateHashValue(lpPath); OBJECTMAP oj; hr = GetFirst_ObjectMap(pConn, dObjectId, oj); if (SUCCEEDED(hr)) { dClassId = oj.dClassId; if (dScopeId) *dScopeId = oj.dObjectScopeId; if (bDeleted) { if (oj.iObjectState == 2) *bDeleted = TRUE; } oj.Clear(); } return hr; } //*************************************************************************** // // CSQLExecProcedure::DeleteProperty // //*************************************************************************** HRESULT CSQLExecProcedure::DeleteProperty(CSQLConnection *pConn, DWORD iPropertyId) { HRESULT hr = WBEM_S_NO_ERROR; // This has to clean up reference counts, if any of these properties // are references. If its an embedded object, we need to remove // all of the instances. // Remove data from all index tables and Class Data. Then remove from // PropertyMap. // We can't allow them to delete a key property if there are instances. // We have to delete qualifiers on the property (Flags&2, RefId = PropertyId) // If a reference, delete object if the ref count is zero. PROPERTYMAP pm; hr = GetFirst_PropertyMap(pConn, iPropertyId, pm); if (SUCCEEDED(hr)) { if (pm.iFlags & REPDRVR_FLAG_KEY) { // We can't remove a key when the class has instances. CLASSDATA cd; hr = GetFirst_ClassDataByPropertyId (pConn, iPropertyId, cd); if (SUCCEEDED(hr)) hr = WBEM_E_INVALID_OPERATION; cd.Clear(); } if (SUCCEEDED(hr)) { // We need to decrement reference counts on // references we are deleting, delete // deleted references with a zero ref count, // and remove embedded objects if (pm.iStorageTypeId == CIM_OBJECT || pm.iStorageTypeId == CIM_REFERENCE) { CLASSDATA cd; SQLIDs ids; hr = GetFirst_ClassDataByPropertyId (pConn, iPropertyId, cd); while (SUCCEEDED(hr)) { ids.push_back(cd.dObjectId); hr = GetNext_ClassData(pConn, cd); if (cd.iPropertyId != iPropertyId) { cd.Clear(); break; } } for (int i = 0; i < ids.size(); i++) { // Embedded objects are deleted if (pm.iStorageTypeId == CIM_OBJECT) hr = DeleteObjectMap(pConn, ids.at(i), TRUE); // References have ref counts decremented. // If their reference count is zero, and they are // marked deleted, delete them now. else if (pm.iStorageTypeId == CIM_REFERENCE) { OBJECTMAP oj; hr = GetFirst_ObjectMap(pConn, ids.at(i), oj); if (SUCCEEDED(hr)) { if (oj.iRefCount <= 1 && oj.iObjectState == 2) hr = DeleteObjectMap(pConn, ids.at(i), TRUE); else { oj.iRefCount--; hr = UpdateObjectMap(pConn, oj, FALSE); } oj.Clear(); } } } } } if (SUCCEEDED(hr)) { // Remove all data for this property.. if (pm.iFlags & (REPDRVR_FLAG_KEY + REPDRVR_FLAG_INDEXED)) hr = DeleteIndexData(pConn, pm.iStorageTypeId, iPropertyId); if (SUCCEEDED(hr)) { // Delete qualifiers on this property. hr = DeletePropQualifiers(pConn, iPropertyId); if (SUCCEEDED(hr)) { // Delete all associated data. hr = DeleteClassData(pConn, iPropertyId); if (SUCCEEDED(hr)) { hr = DeleteClassImages(pConn, iPropertyId); if (SUCCEEDED(hr)) { hr = DeletePropertyMap(pConn, iPropertyId); if (SUCCEEDED(hr)) { hr = DeleteClassKeys(pConn, 0, iPropertyId); } } } } } } } else hr = WBEM_S_NO_ERROR; // OK if not found. return hr; } //*************************************************************************** // // CSQLExecProcedure::DeleteInstanceData // //*************************************************************************** HRESULT CSQLExecProcedure::DeleteInstanceData (CSQLConnection *pConn, SQL_ID dObjectId, DWORD iPropertyId, DWORD iPos) { HRESULT hr = WBEM_S_NO_ERROR; IRowset *pIRowset = NULL; DWORD dwNumRows = 0; wchar_t wSQL[512]; PROPERTYMAP pm; IAccessor *pAccessor = NULL; HACCESSOR hAcc = NULL; hr = GetFirst_PropertyMap(pConn, iPropertyId, pm); if (SUCCEEDED(hr)) { if (pm.iFlags & (REPDRVR_FLAG_KEY + REPDRVR_FLAG_NOT_NULL)) hr = WBEM_E_INVALID_OPERATION; else { if (pm.iStorageTypeId == CIM_OBJECT || pm.iStorageTypeId == CIM_REFERENCE) { CLASSDATA cd; SQLIDs ids; hr = GetFirst_ClassDataByPropertyId (pConn, iPropertyId, cd); while (SUCCEEDED(hr)) { ids.push_back(cd.dObjectId); hr = GetNext_ClassData(pConn, cd); if (cd.iPropertyId != iPropertyId) { cd.Clear(); break; } } for (int i = 0; i < ids.size(); i++) { // Embedded objects are deleted if (pm.iStorageTypeId == CIM_OBJECT) hr = DeleteObjectMap(pConn, ids.at(i), TRUE); // References have ref counts decremented. // If their reference count is zero, and they are // marked deleted, delete them now. else if (pm.iStorageTypeId == CIM_REFERENCE) { OBJECTMAP oj; hr = GetFirst_ObjectMap(pConn, ids.at(i), oj); if (SUCCEEDED(hr)) { if (oj.iRefCount <= 1 && oj.iObjectState == 2) hr = DeleteObjectMap(pConn, ids.at(i), TRUE); else { oj.iRefCount--; hr = UpdateObjectMap(pConn, oj, FALSE); } oj.Clear(); } } } } if (SUCCEEDED(hr)) { hr = DeleteIndexData(pConn, pm.iStorageTypeId, iPropertyId, dObjectId, iPos); if (SUCCEEDED(hr)) { hr = DeleteClassImages(pConn, iPropertyId, dObjectId, iPos); if (SUCCEEDED(hr)) hr = DeleteClassData(pConn, iPropertyId, dObjectId, iPos); } } } } return hr; } //*************************************************************************** // // CSQLExecProcedure::CheckKeyMigration // //*************************************************************************** HRESULT CSQLExecProcedure::CheckKeyMigration(CSQLConnection *pConn, LPWSTR lpObjectKey, LPWSTR lpClassName, SQL_ID dClassId, SQL_ID dScopeID, SQL_ID *pIDs, DWORD iNumIDs) { HRESULT hr = WBEM_S_NO_ERROR; // Make sure this object does not already exist with the same scope and different ClassID. SQL_ID dObjId = CRC64::GenerateHashValue(lpObjectKey); OBJECTMAP oj; hr = GetFirst_ObjectMap(pConn, dObjId, oj); if (SUCCEEDED(hr)) { if (oj.dObjectScopeId == dScopeID && dClassId != oj.dClassId) hr = WBEM_E_ALREADY_EXISTS; oj.Clear(); } else if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; // OK if not found. return hr; } HRESULT CSQLExecProcedure::NeedsToCheckKeyMigration(BOOL &bCheck) { bCheck = TRUE; return 0; } HRESULT CSQLExecProcedure::Execute (CSQLConnection *pConn, LPCWSTR lpProcName, CWStringArray &arrValues, IRowset **ppIRowset) { return E_NOTIMPL; } //*************************************************************************** // // CSQLExecProcedure::HasInstances // //*************************************************************************** HRESULT CSQLExecProcedure::HasInstances(CSQLConnection *pConn, SQL_ID dClassId, SQL_ID *pDerivedIds, DWORD iNumDerived, BOOL &bInstancesExist) { HRESULT hr = WBEM_S_NO_ERROR; bInstancesExist = FALSE; // We need to query the table for any instance of this class // or any of its children. OBJECTMAP oj; hr = GetFirst_ObjectMapByClass(pConn, dClassId, oj); if (SUCCEEDED(hr)) { while (SUCCEEDED(hr)) { if (oj.iObjectState == 0) { bInstancesExist = TRUE; break; } hr = GetNext_ObjectMap(pConn, oj); if (oj.dClassId != dClassId) break; } oj.Clear(); } if (!bInstancesExist) { for (int i = 0; i < iNumDerived; i++) { hr = GetFirst_ObjectMapByClass(pConn, pDerivedIds[i], oj); while (hr == WBEM_S_NO_ERROR) { if (oj.iObjectState == 0) { bInstancesExist = TRUE; break; } hr = GetNext_ObjectMap(pConn, oj); if (pDerivedIds[i] != oj.dClassId) break; } } } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; return hr; } //*************************************************************************** // // CSQLExecProcedure::InsertClass // //*************************************************************************** HRESULT CSQLExecProcedure::InsertClass (CSQLConnection *pConn, LPCWSTR lpClassName, LPCWSTR lpObjectKey, LPCWSTR lpObjectPath, SQL_ID dScopeID, SQL_ID dParentClassId, SQL_ID dDynasty, DWORD iState, BYTE *pClassBuff, DWORD dwClassBuffLen, DWORD iClassFlags, DWORD iInsertFlags, SQL_ID &dNewId) { HRESULT hr = WBEM_S_NO_ERROR; SQL_ID dClassId = 0; BOOL bExists = FALSE; BOOL bDeleted = FALSE; OBJECTMAP oj; if (!dNewId) dNewId = CRC64::GenerateHashValue(lpObjectKey); if (!dDynasty) dDynasty = dNewId; // Reports to self. hr = GetFirst_ObjectMap(pConn, dNewId, oj); if (SUCCEEDED(hr)) { dClassId = oj.dClassId; bExists = TRUE; if (bDeleted && (iInsertFlags & WBEM_FLAG_UPDATE_ONLY)) hr = WBEM_E_INVALID_OBJECT; else if (iInsertFlags & WBEM_FLAG_CREATE_ONLY && (!bDeleted)) hr = WBEM_E_ALREADY_EXISTS; else hr = WBEM_S_NO_ERROR; oj.Clear(); } else if (iInsertFlags & WBEM_FLAG_UPDATE_ONLY) hr = WBEM_E_INVALID_OBJECT; else hr = WBEM_S_NO_ERROR; if (dClassId != 1 && dParentClassId == 0) dParentClassId = 1; else if (dParentClassId == dNewId) hr = WBEM_E_CIRCULAR_REFERENCE; if (SUCCEEDED(hr)) { BOOL bInsert = TRUE; if (bExists) bInsert = FALSE; if (!dNewId) dNewId = CRC64::GenerateHashValue(lpObjectKey); LPWSTR lpPath = StripQuotes((LPWSTR)lpObjectPath); CDeleteMe d (lpPath); // Insert ObjectMap hr = InsertObjectMap(pConn, dNewId, lpObjectKey, iState, lpPath, dScopeID, iClassFlags, 0, 1, bInsert); if (SUCCEEDED(hr)) { hr = InsertClassMap(pConn, dNewId, lpClassName, dParentClassId, dDynasty, pClassBuff, dwClassBuffLen, bInsert); if (SUCCEEDED(hr)) { if (iInsertFlags & WMIDB_HANDLE_TYPE_AUTODELETE) { hr = InsertAutoDelete(pConn, dNewId); } } } } return hr; } //*************************************************************************** // // CSQLExecProcedure::InsertClassData // //*************************************************************************** HRESULT CSQLExecProcedure::InsertClassData (CSQLConnection *pConn, IWbemClassObject *pObj, CSchemaCache *pCache, SQL_ID dScopeId, SQL_ID dClassId, LPCWSTR lpPropName, DWORD CIMType, DWORD StorageType,LPCWSTR lpValue, SQL_ID dRefClassId, DWORD iPropID, DWORD iFlags, DWORD iFlavor, BOOL iSkipValid, DWORD &iNewPropId, SQL_ID dOrigClassId, BOOL *bIsKey) { HRESULT hr = WBEM_S_NO_ERROR; SQL_ID dClass = dOrigClassId; if (!dClass) dClass = dClassId; DWORD dwNumRows = 0; BOOL bHasKey = FALSE; if (iFlags & REPDRVR_FLAG_QUALIFIER) dClass = 1; if (iNewPropId) { BOOL bLocal = FALSE; BOOL bKey = pCache->IsKey(dClassId, iNewPropId, bLocal); PROPERTYMAP pm; hr = GetFirst_PropertyMap(pConn, iNewPropId, pm); if (SUCCEEDED(hr) && pm.iStorageTypeId != StorageType) { if (StorageType == WMIDB_STORAGE_REAL && pm.iStorageTypeId == WMIDB_STORAGE_NUMERIC) { hr = InsertPropertyMap(pConn, iNewPropId, dClassId, StorageType, CIMType, lpPropName, iFlags, FALSE); // They changed the datatype. If this used to be an int, // (the only acceptable move) we have to move the data, // including any default and index, to the new column, table. CLASSDATA pm; hr = GetFirst_ClassDataByPropertyId(pConn, iNewPropId, pm); while (SUCCEEDED(hr)) { pm.rPropertyRealValue = pm.dPropertyNumericValue; pm.dPropertyNumericValue = 0; hr = UpdateClassData_Internal(pConn, pm); if (FAILED(hr)) { pm.Clear(); break; } hr = GetNext_ClassData(pConn, pm); if (pm.iPropertyId != iNewPropId) { pm.Clear(); break; } } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; if (SUCCEEDED(hr)) { if (iFlags & (REPDRVR_FLAG_INDEXED + REPDRVR_FLAG_KEY)) { INDEXDATA id; JET_TABLEID tid = 0; DWORD dwPos = 0; hr = GetFirst_IndexDataByProperty(pConn, iNewPropId, id, tid, dwPos); while (SUCCEEDED(hr)) { hr = InsertIndexData(pConn, dClassId, iNewPropId, id.iArrayPos, id.sValue, id.dValue, id.rValue, WMIDB_STORAGE_REAL); if (FAILED(hr)) break; hr = GetNext_IndexData(pConn, tid, dwPos, id); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; if (SUCCEEDED(hr)) DeleteIndexData(pConn, WMIDB_STORAGE_NUMERIC, iNewPropId); } } } else hr = WBEM_E_INVALID_OPERATION; } if (dRefClassId) hr = InsertReferenceProperties (pConn, dClassId, iNewPropId, dRefClassId, FALSE); if (!bKey && (iFlags & REPDRVR_FLAG_KEY)) { hr = InsertClassKeys(pConn, dClassId, iNewPropId); bKey = TRUE; } if (!bLocal && bKey) bKey = FALSE; if (bIsKey) *bIsKey = bKey; } else { BOOL bInsert = TRUE; if (iNewPropId) bInsert = FALSE; hr = InsertPropertyMap(pConn, iNewPropId, dClassId, StorageType, CIMType, lpPropName, iFlags, bInsert); if (SUCCEEDED(hr)) { if (CIMType == CIM_REFERENCE) { if (dRefClassId) hr = InsertReferenceProperties (pConn, dClassId, iNewPropId, dRefClassId, FALSE); else { hr = DeleteReferenceProperties(pConn, iNewPropId, dClassId); if (REPDRVR_FLAG_CLASSREFS & iFlags) { // Enumerate the class refs on this property. IWbemQualifierSet *pQS = NULL; hr = pObj->GetPropertyQualifierSet(lpPropName, &pQS); if (SUCCEEDED(hr)) { VARIANT vValue; VariantInit(&vValue); CReleaseMe r (pQS); CClearMe c (&vValue); hr = pQS->Get(L"ClassRef", 0, &vValue, NULL); if (SUCCEEDED(hr) && vValue.vt == VT_BSTR+CIM_FLAG_ARRAY) { SAFEARRAY *psaArray = V_ARRAY(&vValue); if (psaArray) { VARIANT vVal; VariantInit(&vVal); CClearMe c (&vVal); long lLBound, lUBound; SafeArrayGetLBound(psaArray, 1, &lLBound); SafeArrayGetUBound(psaArray, 1, &lUBound); lUBound -= lLBound; lUBound += 1; for (int i = 0; i < lUBound; i++) { hr = GetVariantFromArray(psaArray, i, VT_BSTR, vVal); if (SUCCEEDED(hr)) { SQL_ID dRefClass = 0; hr = pCache->GetClassID(vVal.bstrVal, dScopeId, dRefClass); if (SUCCEEDED(hr)) { hr = InsertReferenceProperties(pConn, dClassId, iNewPropId, dRefClass, TRUE); } } } } } } } } } if (SUCCEEDED(hr)) { if ((iFlags & REPDRVR_FLAG_KEY)) { hr = InsertClassKeys(pConn, dClassId, iNewPropId); if (bIsKey) *bIsKey = TRUE; } else if (bIsKey) *bIsKey = FALSE; } } } if (SUCCEEDED(hr)) { BOOL bLocal = FALSE; if (!(iFlags & REPDRVR_FLAG_KEY) && pCache->IsKey(dClassId, iNewPropId, bLocal)) { pCache->SetIsKey(dClassId, iNewPropId, FALSE); hr = DeleteClassKeys(pConn, dClassId, iNewPropId); if (bIsKey) *bIsKey = FALSE; } } return hr; } //*************************************************************************** // // CSQLExecProcedure::InsertBlobData // //*************************************************************************** HRESULT CSQLExecProcedure::InsertBlobData (CSQLConnection *pConn, SQL_ID dClassId, SQL_ID dObjectId, DWORD iPropertyId, BYTE *pImage, DWORD iPos, DWORD dwNumBytes) { return InsertClassImages (pConn, dObjectId, iPropertyId, iPos, pImage, dwNumBytes); } //*************************************************************************** // // CSQLExecProcedure::InsertPropertyBatch // //*************************************************************************** HRESULT CSQLExecProcedure::InsertPropertyBatch (CSQLConnection *pConn, LPCWSTR lpObjectKey, LPCWSTR lpPath, LPCWSTR lpClassName, SQL_ID dClassId, SQL_ID dScopeId, DWORD iInsertFlags, InsertPropValues *pVals, DWORD iNumVals, SQL_ID &dNewObjectId) { HRESULT hr = WBEM_S_NO_ERROR; BOOL bExists = FALSE; BOOL bDeleted = FALSE; // Find existing ID, based on lpObjectKey. // Verify insert/update flags if (!dNewObjectId) { SQL_ID dTemp; hr = GetObjectIdByPath(pConn, lpObjectKey, dNewObjectId, dTemp, NULL, &bDeleted); if (SUCCEEDED(hr)) { bExists = TRUE; if ((!bDeleted) && iInsertFlags & WBEM_FLAG_CREATE_ONLY) hr = WBEM_E_ALREADY_EXISTS; else if (bDeleted && (iInsertFlags & WBEM_FLAG_UPDATE_ONLY)) hr = WBEM_E_INVALID_OBJECT; else hr = WBEM_S_NO_ERROR; } else if (iInsertFlags & WBEM_FLAG_UPDATE_ONLY) hr = WBEM_E_INVALID_OBJECT; else hr = WBEM_S_NO_ERROR; dNewObjectId = CRC64::GenerateHashValue(lpObjectKey); } else bExists = TRUE; if (SUCCEEDED(hr)) { BOOL bInsert = TRUE; if (bExists) bInsert = FALSE; LPWSTR lpPath2 = StripQuotes((LPWSTR)lpPath); CDeleteMe d (lpPath2); hr = InsertObjectMap(pConn, dNewObjectId, lpObjectKey, 0, lpPath2, dScopeId, 0, 0, dClassId, bInsert); if (SUCCEEDED(hr) && bExists) { // Delete all qualifiers, since we will reinsert them all. // (Guess we can't do this through accessors.) hr = DeleteQualifiers(pConn, dNewObjectId); if (SUCCEEDED(hr)) { if (iInsertFlags & WMIDB_HANDLE_TYPE_AUTODELETE) hr = InsertAutoDelete(pConn, dNewObjectId); } } if (SUCCEEDED(hr)) hr = InsertBatch(pConn, dNewObjectId, dScopeId, dClassId, pVals, iNumVals); } return hr; } //*************************************************************************** // // CSQLExecProcedure::InsertBatch // //*************************************************************************** HRESULT CSQLExecProcedure::InsertBatch (CSQLConnection *pConn, SQL_ID dObjectId, SQL_ID dScopeId, SQL_ID dClassId, InsertQfrValues *pVals, DWORD iNumVals) { HRESULT hr = WBEM_S_NO_ERROR; // Insert each property/qualifier/method/method parameter: if (dClassId == CONTAINERASSOCID) { for (int i = 0; i < iNumVals; i++) { if (pVals[i].pRefKey != NULL) { SQL_ID dContaineeId = _wtoi64(pVals[i].pRefKey); SQL_ID dContainerId = _wtoi64(pVals[i+1].pRefKey); hr = InsertContainerObjs(pConn, dContainerId, dContaineeId); if (FAILED(hr)) goto Exit; break; } } } for (int i = 0; i < iNumVals; i++) { SQL_ID dRefID = 0, dRefClassID = 0; BOOL bExisting = FALSE, bEx2 = FALSE; IRowset *pIRowset = NULL; InsertQfrValues *pVal = &pVals[i]; DWORD dwRows = 0; LPWSTR lpVal = NULL; BOOL bRefCount = FALSE; LPWSTR sVal = NULL; SQL_ID dVal = 0; double rVal = 0; bool bStoreTextAsImage = false; BOOL bIsNull = FALSE; switch(pVal->iStorageType) { case WMIDB_STORAGE_STRING: if (pVal->pValue) { sVal = TruncateLongText(pVal->pValue, 127, bStoreTextAsImage, 127); if (bStoreTextAsImage) pVal->bLong = TRUE; } else bIsNull = TRUE; // Clean up any previously-created string data stored as images. hr = DeleteClassImages(pConn, pVal->iPropID, dObjectId, pVal->iPos); hr = InsertClassData_Internal (pConn, dObjectId, pVal->iPropID, pVal->iPos, pVal->iQfrID, pVal->dClassId, sVal, 0, 0, pVal->iFlavor, pVal->iQfrID, 0, bIsNull); if (SUCCEEDED(hr) && pVal->bIndexed) { hr = InsertIndexData (pConn, dObjectId, pVal->iPropID, pVal->iPos, sVal, 0, 0, pVal->iStorageType); } delete sVal; break; case WMIDB_STORAGE_NUMERIC: if (pVal->pValue) dVal = _wtoi64(pVal->pValue); else bIsNull = TRUE; hr = InsertClassData_Internal (pConn, dObjectId, pVal->iPropID, pVal->iPos, pVal->iQfrID, pVal->dClassId, NULL, dVal, 0, pVal->iFlavor, pVal->iQfrID, 0, bIsNull); if (SUCCEEDED(hr) && pVal->bIndexed) { hr = InsertIndexData (pConn, dObjectId, pVal->iPropID, pVal->iPos, NULL, dVal, 0, pVal->iStorageType); } break; case WMIDB_STORAGE_REAL: if (pVal->pValue) rVal = wcstod(pVal->pValue, &lpVal); else bIsNull = TRUE; hr = InsertClassData_Internal (pConn, dObjectId, pVal->iPropID, pVal->iPos, pVal->iQfrID, pVal->dClassId, NULL, 0, rVal, pVal->iFlavor, pVal->iQfrID, 0, bIsNull); if (SUCCEEDED(hr) && pVal->bIndexed) { hr = InsertIndexData (pConn, dObjectId, pVal->iPropID, pVal->iPos, NULL, rVal, 0, pVal->iStorageType); } break; case WMIDB_STORAGE_REFERENCE: // * If this is a reference, we need to get the ID from the key string. // If this object does not exist, we need to insert a bogus row. // Bump up the ref count. // If this is an update, decrement the ref count on previous row // If previous row now has zero ref count, remove it. dRefID = _wtoi64(pVal->pRefKey); { IRowset *pRowset = NULL; IAccessor *pAccessor = NULL; HACCESSOR hAcc = NULL; CLASSDATA cd; BOOL bOldRow = FALSE; hr = GetFirst_ClassData(pConn, dObjectId, cd,pVal->iPropID); while (hr == WBEM_S_NO_ERROR) { if (pVal->iPos == cd.iArrayPos && pVal->iQfrID == cd.iQfrPos) { bExisting = TRUE; SQL_ID dOldRefID = cd.dRefId; if (dRefID != dOldRefID) { PROPERTYMAP pm; hr = GetFirst_PropertyMap(pConn, pVal->iPropID, pm); if (SUCCEEDED(hr)) { if (pm.iCIMTypeId == CIM_OBJECT) hr = DeleteObjectMap(pConn, dOldRefID, TRUE); else { OBJECTMAP om; hr = GetFirst_ObjectMap(pConn, dOldRefID, om); if (SUCCEEDED(hr)) { bOldRow = TRUE; bRefCount = TRUE; if (om.iRefCount) om.iRefCount--; hr = UpdateObjectMap(pConn, om); om.Clear(); } } } } else bOldRow = TRUE; cd.Clear(); break; } hr = GetNext_ClassData(pConn, cd, pVal->iPropID); if (cd.dObjectId != dObjectId) { cd.Clear(); break; } } hr = 0; if (!bOldRow) bRefCount = TRUE; } if (pVal->pValue) { lpVal = StripQuotes(pVal->pValue); ObjectExists(pConn, dRefID, bEx2, &dRefClassID, NULL, TRUE); if (!bEx2) { // We need to insert this row and get the new ID. LPWSTR lpKey = GetKeyString(pVal->pValue); CDeleteMe d (lpKey); hr = InsertObjectMap(pConn, dRefID, lpKey, 2, lpVal, dObjectId, 1, 1, 0, TRUE); } else if (bRefCount) { IRowset *pRowset = NULL; IAccessor *pAccessor = NULL; HACCESSOR hAcc = NULL; OBJECTMAP om; hr = GetFirst_ObjectMap(pConn, dRefID, om); if (SUCCEEDED(hr)) { om.iRefCount++; hr = UpdateObjectMap(pConn, om); om.Clear(); } } if (SUCCEEDED(hr)) { // update/insert the new row sVal = TruncateLongText(pVal->pValue, 127, bStoreTextAsImage, 127); if (bStoreTextAsImage) pVal->bLong = TRUE; hr = InsertClassData_Internal (pConn, dObjectId, pVal->iPropID, pVal->iPos, pVal->iQfrID, pVal->dClassId, sVal, 0, 0, pVal->iFlavor, dRefID, dRefClassID, FALSE); if (SUCCEEDED(hr) && pVal->bIndexed) { DWORD dwRows = 0; hr = InsertIndexData (pConn, dObjectId, pVal->iPropID, pVal->iPos, sVal, dRefID, 0, pVal->iStorageType); } delete sVal; } delete lpVal; } break; // This should never be hit. default: pVal->bLong = TRUE; continue; } if (FAILED(hr)) break; } if (SUCCEEDED(hr)) { // If our text was too long, we need to store it as an image. for (i = 0; i < iNumVals; i++) { if (pVals[i].bLong) { if (pVals[i].iStorageType == WMIDB_STORAGE_STRING || pVals[i].iStorageType == WMIDB_STORAGE_REFERENCE) { LPWSTR lpTemp = StripQuotes2 (pVals[i].pValue); CDeleteMe d (lpTemp); hr = InsertBlobData (pConn, dClassId, dObjectId, pVals[i].iPropID, (BYTE *)lpTemp, 0, wcslen(lpTemp)*2+2); } else if (pVals[i].pValue == NULL) // This is a null blob! hr = DeleteClassImages(pConn, pVals[i].iPropID, dObjectId); else { ERRORTRACE((LOG_WBEMCORE, "Invalid argument in InsertBatch (Obj %I64d, Class %I64d, Prop %ld)", \ dObjectId, dClassId, pVals[i].iPropID)); } } delete pVals[i].pValue; delete pVals[i].pRefKey; } } Exit: return hr; } //*************************************************************************** // // CSQLExecProcedure::ObjectExists // //*************************************************************************** HRESULT CSQLExecProcedure::ObjectExists (CSQLConnection *pConn, SQL_ID dId, BOOL &bExists, SQL_ID *_dClassId, SQL_ID *_dScopeId, BOOL bDeletedOK) { SQL_ID dClassId, dScopeId; BOOL bDeleted = FALSE; OBJECTMAP oj; HRESULT hr = GetFirst_ObjectMap(pConn, dId, oj); if (SUCCEEDED(hr)) { bExists = TRUE; if (oj.iObjectState == 2) { if (!bDeletedOK) bExists = FALSE; } if (bExists) { if (_dClassId) *_dClassId = oj.dClassId; if (_dScopeId) *_dScopeId = oj.dObjectScopeId; } oj.Clear(); } return hr; } //*************************************************************************** // // CSQLExecProcedure::RenameSubscopes // //*************************************************************************** HRESULT CSQLExecProcedure::RenameSubscopes (CSQLConnection *pConn, LPWSTR lpOldPath, LPWSTR lpOldKey, LPWSTR lpNewPath, LPWSTR lpNewKey) { HRESULT hr = 0; OBJECTMAP om; // Enumerate all objects, and rename any that begin with the old path string. hr = SetupObjectMapAccessor(pConn); if (SUCCEEDED(hr)) { int iOldPathLen = wcslen(lpOldPath); int iOldKeyLen = wcslen(lpOldKey); SQL_ID OldId = CRC64::GenerateHashValue(lpOldKey); SQL_ID NewId = CRC64::GenerateHashValue(lpNewKey); hr = OpenEnum_ObjectMap(pConn, om); if (SUCCEEDED(hr)) { if (!_wcsnicmp(om.sObjectPath, lpOldPath, iOldPathLen)) { // Path = @NewPath + substring(ObjectPath, @OldPathLen+1, (datalength(ObjectPath)/2)- @OldPathLen), // Key = substring(ObjectKey, 1, charindex(@OldKey, ObjectKey)-1) +@NewKey LPWSTR lpTemp = NULL; if (wcslen(om.sObjectPath) > iOldPathLen) { lpTemp = &om.sObjectPath[iOldPathLen]; LPWSTR lpNew = new wchar_t [wcslen(om.sObjectPath) + wcslen(lpNewPath)+1]; CDeleteMe d(lpNew); if (lpNew) { wcscpy(lpNew, lpNewPath); wcscat(lpNew, lpTemp); om.sObjectPath = SysAllocString(lpNew); LPWSTR lpNew2 = new wchar_t [wcslen(om.sObjectKey) + wcslen(lpNewKey) + 1]; if (lpNew2 && om.sObjectPath) { lpTemp = om.sObjectKey; lpTemp[iOldKeyLen] = L'\0'; wcscpy(lpNew2, lpTemp); wcscat(lpNew2, lpNewKey); om.sObjectKey = SysAllocString(lpNew2); if (om.dObjectScopeId == OldId) om.dObjectScopeId = NewId; if (om.dClassId == OldId) om.dClassId = NewId; if (om.dObjectId == OldId) om.dObjectId = NewId; hr = UpdateObjectMap(pConn, om); } else hr = WBEM_E_OUT_OF_MEMORY; } else hr = WBEM_E_OUT_OF_MEMORY; } else { om.sObjectPath = SysAllocString(lpNewPath); om.sObjectKey = SysAllocString(lpNewKey); if (om.sObjectPath && om.sObjectKey) hr = UpdateObjectMap(pConn, om); else hr = WBEM_E_OUT_OF_MEMORY; } } else if (om.sObjectPath[0] > lpOldPath[0]) om.Clear(); hr = GetNext_ObjectMap(pConn, om); } // FIXME: We don't currently update ClassData and IndexRefData! // IF this is a class, we don't update the ClassMap and PropertyMap!!! if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; } return hr; } //*************************************************************************** // // CSQLExecProcedure::GetSecurityDescriptor // //*************************************************************************** HRESULT CSQLExecProcedure::GetSecurityDescriptor(CSQLConnection *pConn, SQL_ID dObjectId, PNTSECURITY_DESCRIPTOR * ppSD, DWORD &dwBuffLen, DWORD dwFlags) { HRESULT hr = WBEM_S_NO_ERROR; // If this is a class , get the security for __ClassSecurity (WMIDB_SECURITY_FLAG_CLASS) // or __Instances container (WMIDB_SECURITY_FLAG_INSTANCE) // If this is a namespace, get the security for __ThisNamespace // Otherwise, get it off the object itself. // Make sure its a valid security descriptor, before we // return anything. *ppSD = NULL; PNTSECURITY_DESCRIPTOR pSD = NULL; dwBuffLen = 0; OBJECTMAP oj; CLASSMAP cm; SQL_ID dID = 0; hr = GetFirst_ClassMap(pConn, dObjectId, cm); if (SUCCEEDED(hr)) { LPWSTR lpRetrievalName = NULL; SQL_ID dScopeId = oj.dObjectScopeId; int iSize = 0; oj.Clear(); // We need to generate the path of the class if (dwFlags == WMIDB_SECURITY_FLAG_INSTANCE) { if (dScopeId) { hr = GetFirst_ObjectMap(pConn, dScopeId, oj); iSize = wcslen(oj.sObjectPath) + wcslen(cm.sClassName) + 128; } else iSize = wcslen(cm.sClassName) + 128; lpRetrievalName = new wchar_t [iSize]; CDeleteMe d (lpRetrievalName); if (lpRetrievalName) { if (dScopeId) swprintf(lpRetrievalName, L"%s:__ClassInstancesSecurity=\"%s\"", oj.sObjectPath, cm.sClassName); else swprintf(lpRetrievalName, L"__ClassInstancesSecurity=\"%s\"", cm.sClassName); LPWSTR lpKey = GetKeyString(lpRetrievalName); CDeleteMe d2 (lpKey); if (lpKey) { dID = CRC64::GenerateHashValue(lpKey); } else hr = WBEM_E_OUT_OF_MEMORY; } else hr = WBEM_E_OUT_OF_MEMORY; } else { // Get the __ClassSecurity object if (dScopeId) { hr = GetFirst_ObjectMap(pConn, dScopeId, oj); iSize = wcslen(oj.sObjectPath) + wcslen(cm.sClassName) + 128; } else iSize = wcslen(cm.sClassName) + 128; lpRetrievalName = new wchar_t [iSize]; CDeleteMe d (lpRetrievalName); if (lpRetrievalName) { if (dScopeId) swprintf(lpRetrievalName, L"%s:__ClassSecurity=\"%s\"", oj.sObjectPath, cm.sClassName); else swprintf(lpRetrievalName, L"__ClassSecurity=\"%s\"", cm.sClassName); LPWSTR lpKey = GetKeyString(lpRetrievalName); CDeleteMe d2 (lpKey); if (lpKey) { dID = CRC64::GenerateHashValue(lpKey); } else hr = WBEM_E_OUT_OF_MEMORY; } else hr = WBEM_E_OUT_OF_MEMORY; } cm.Clear(); oj.Clear(); } else { // Get the object itself. hr = WBEM_S_NO_ERROR; dID = dObjectId; oj.Clear(); } if (SUCCEEDED(hr)) { CLASSIMAGES ci; BOOL bFound = FALSE; hr = GetFirst_ClassImages(pConn, dID, ci); while (SUCCEEDED(hr)) { PROPERTYMAP pm; hr = GetFirst_PropertyMap(pConn, ci.iPropertyId, pm); if (SUCCEEDED(hr) && (!_wcsicmp(pm.sPropertyName, L"__SECURITY_DESCRIPTOR"))) { pSD = ci.pBuffer; bFound = TRUE; if (pSD != NULL) { if (IsValidSecurityDescriptor(pSD)) { // Make a copy of it. pSD = (PNTSECURITY_DESCRIPTOR)CWin32DefaultArena::WbemMemAlloc(ci.dwBufferLen); ZeroMemory(pSD, ci.dwBufferLen); memcpy(pSD, ci.pBuffer, ci.dwBufferLen); *ppSD = pSD; dwBuffLen = ci.dwBufferLen; } } } pm.Clear(); if (bFound) break; hr = GetNext_ClassImages(pConn, ci); } ci.Clear(); } return hr; } //*************************************************************************** // // CSQLExecProcedure::EnumerateSecuredChildren // //*************************************************************************** HRESULT CSQLExecProcedure::EnumerateSecuredChildren(CSQLConnection *pConn, CSchemaCache *pCache, SQL_ID dObjectId, SQL_ID dClassId, SQL_ID dScopeId, SQLIDs &ObjIds, SQLIDs &ClassIds, SQLIDs &ScopeIds) { HRESULT hr = WBEM_S_NO_ERROR; // If __Classes instance, we need to enumerate all instances of __ClassSecurity // If this is a __ClassSecurity instance, we need to enumerate all instances // of __ClassSecurity for all subclasses // If this is a __ClassInstancesSecurity instance, we need to enumerate all // instances of this class // If this is a namespace (__ThisNamespace) or scope, we need all subscoped objects SQL_ID dClassSecurityId = CLASSSECURITYID; SQL_ID dClassesId = CLASSESID; SQL_ID dClassInstSecurityId = CLASSINSTSECID; SQL_ID dThisNamespaceId = THISNAMESPACEID; DWORD dwSecPropID = 0; hr = pCache->GetPropertyID(L"__SECURITY_DESCRIPTOR", 1, 0, REPDRVR_IGNORE_CIMTYPE, dwSecPropID); if (dClassId == dClassesId) { // All classes in this namespace. OBJECTMAP oj; hr = GetFirst_ObjectMapByClass(pConn, dClassSecurityId, oj); while (SUCCEEDED(hr)) { if (oj.dObjectScopeId == dScopeId) { // This is pointing to some class, we don't care // which one. CLASSIMAGES ci; hr = GetFirst_ClassImages(pConn, oj.dObjectId, ci); while (SUCCEEDED(hr)) { if (ci.iPropertyId == dwSecPropID) { ObjIds.push_back(oj.dObjectId); ClassIds.push_back(oj.dClassId); ScopeIds.push_back(oj.dObjectScopeId); ci.Clear(); break; } hr = GetNext_ClassImages(pConn, ci); } } hr = GetNext_ObjectMap(pConn, oj); } } else if (dClassId == dClassSecurityId) { // All __ClassSecurity for subclasses of this class // Get the class name // Get the ID for the class name in this namespace // Enumerate subclasses // Format the name // Generate the Object ID return E_NOTIMPL; } else if (dClassId == dClassInstSecurityId) { // All instances of this class and subclasses. // Get the class name // Get the ID for the class name in this namespace // Enumerate subclasses // Enumerate all instances of each class return E_NOTIMPL; } else { // Regular instance. Enumerate all objects // scoped to this . SQL_ID dThis = dObjectId; if (dClassId == dThisNamespaceId) dThis = dScopeId; SQL_ID * pScopes = NULL; int iNumScopes = 0; hr = pCache->GetSubScopes(dThis, &pScopes, iNumScopes); for (int i = 0; i < iNumScopes; i++) { OBJECTMAP oj; hr = GetFirst_ObjectMapByScope(pConn, pScopes[i], oj); while (SUCCEEDED(hr)) { CLASSIMAGES ci; hr = GetFirst_ClassImages(pConn, oj.dObjectId, ci); while (SUCCEEDED(hr)) { if (ci.iPropertyId == dwSecPropID) { ObjIds.push_back(oj.dObjectId); ClassIds.push_back(oj.dClassId); ScopeIds.push_back(oj.dObjectScopeId); ci.Clear(); break; } hr = GetNext_ClassImages(pConn, ci); } hr = GetNext_ObjectMap(pConn, oj); } } delete pScopes; } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; return hr; } //*************************************************************************** // // CSQLExecProcedure::EnumerateSubScopes // //*************************************************************************** HRESULT CSQLExecProcedure::EnumerateSubScopes (CSQLConnection *pConn, SQL_ID dScopeId) { return E_NOTIMPL; } //*************************************************************************** // // CSQLExecProcedure::InsertScopeMap // //*************************************************************************** HRESULT CSQLExecProcedure::InsertScopeMap (CSQLConnection *pConn, SQL_ID dScopeId, LPCWSTR lpScopePath, SQL_ID dParentId) { HRESULT hr = InsertScopeMap_Internal(pConn, dScopeId, lpScopePath, dParentId); return hr; } //*************************************************************************** // // CSQLExecProcedure::InsertUncommittedEvent // //*************************************************************************** HRESULT CSQLExecProcedure::InsertUncommittedEvent (CSQLConnection *pConn, LPCWSTR lpGUID, LPWSTR lpNamespace, LPWSTR lpClassName, IWbemClassObject *pOldObj, IWbemClassObject *pNewObj, CSchemaCache *pCache) { HRESULT hr = WBEM_S_NO_ERROR; static int iNumProps = 4; InsertPropValues *pVals = new InsertPropValues[iNumProps]; if (!pVals) return WBEM_E_OUT_OF_MEMORY; CDeleteMe d (pVals); LPWSTR lpObjectKey = NULL, lpPath = NULL; SQL_ID dScopeId = 1; SQL_ID dObjectId = 0; SQL_ID dKeyhole = 0; static SQL_ID dClassId = 0; static DWORD dwPropId1 = 0, dwPropId2 = 0, dwPropId3 = 0, dwPropId4 = 0, dwPropId5 = 0, dwPropId6 = 0, dwPropId7 = 0; if (!dwPropId1) { hr = pCache->GetClassID(L"__UncommittedEvent", 1, dClassId); if (SUCCEEDED(hr)) { hr = pCache->GetPropertyID(L"EventID", dClassId, 0, REPDRVR_IGNORE_CIMTYPE, dwPropId1); hr = pCache->GetPropertyID(L"TransactionGUID", dClassId, 0, REPDRVR_IGNORE_CIMTYPE, dwPropId2); hr = pCache->GetPropertyID(L"NamespaceName", dClassId, 0, REPDRVR_IGNORE_CIMTYPE, dwPropId3); hr = pCache->GetPropertyID(L"ClassName", dClassId, 0, REPDRVR_IGNORE_CIMTYPE, dwPropId4); hr = pCache->GetPropertyID(L"OldObject", dClassId, 0, REPDRVR_IGNORE_CIMTYPE, dwPropId5); hr = pCache->GetPropertyID(L"NewObject", dClassId, 0, REPDRVR_IGNORE_CIMTYPE, dwPropId6); hr = pCache->GetPropertyID(L"Transacted", dClassId, 0, REPDRVR_IGNORE_CIMTYPE, dwPropId7); } } if (FAILED(hr)) return hr; hr = GetNextKeyhole(pConn, dwPropId1, dKeyhole); if (SUCCEEDED(hr)) { LPWSTR lpKey = new wchar_t [40]; lpObjectKey = new wchar_t [100]; lpPath = new wchar_t [100]; CDeleteMe d2 (lpKey), d3 (lpObjectKey), d4 (lpPath); if (!lpKey || !lpObjectKey || !lpPath) return WBEM_E_OUT_OF_MEMORY; swprintf(lpKey, L"%ld", dKeyhole); swprintf(lpObjectKey, L"%ld?__UncommittedEvent", dKeyhole); swprintf(lpObjectKey, L"__UncommittedEvent=%ld", dKeyhole); pVals[0].iPropID = dwPropId1; pVals[0].bIndexed = TRUE; pVals[0].iStorageType = WMIDB_STORAGE_NUMERIC; pVals[0].dClassId = dClassId; pVals[0].pValue = lpKey; pVals[1].iPropID = dwPropId2; pVals[1].bIndexed = TRUE; pVals[1].iStorageType = WMIDB_STORAGE_STRING; pVals[1].dClassId = dClassId; pVals[1].pValue = (LPWSTR)lpGUID; pVals[2].iPropID = dwPropId3; pVals[2].iStorageType = WMIDB_STORAGE_STRING; pVals[2].dClassId = dClassId; pVals[2].pValue = lpClassName; pVals[3].iPropID = dwPropId4; pVals[3].iStorageType = WMIDB_STORAGE_STRING; pVals[3].dClassId = dClassId; pVals[3].pValue = (LPWSTR)lpNamespace; pVals[4].iPropID = dwPropId6; pVals[4].iStorageType = WMIDB_STORAGE_NUMERIC; pVals[4].dClassId = dClassId; pVals[4].pValue = new wchar_t [1]; if (!pVals[4].pValue) return WBEM_E_OUT_OF_MEMORY; wcscpy(pVals[4].pValue, L"1"); hr = InsertPropertyBatch (pConn, lpObjectKey, lpPath, lpClassName, dClassId, dScopeId, 0, pVals, iNumProps, dObjectId); if (SUCCEEDED(hr)) { if (pOldObj) { _IWmiObject *pInt = NULL; hr = pOldObj->QueryInterface(IID__IWmiObject, (void **)&pInt); if (SUCCEEDED(hr)) { DWORD dwLen = 0; pInt->GetObjectMemory(NULL, 0, &dwLen); BYTE *pBuff = new BYTE [dwLen]; if (pBuff) { CDeleteMe d (pBuff); DWORD dwLen1; hr = pInt->GetObjectMemory(pBuff, dwLen, &dwLen1); if (SUCCEEDED(hr)) { hr = CSQLExecProcedure::InsertBlobData(pConn, dClassId, dObjectId, dwPropId4, pBuff, 0, dwLen); } } else hr = WBEM_E_OUT_OF_MEMORY; pInt->Release(); } } if (pNewObj) { _IWmiObject *pInt = NULL; hr = pNewObj->QueryInterface(IID__IWmiObject, (void **)&pInt); if (SUCCEEDED(hr)) { DWORD dwLen = 0; pInt->GetObjectMemory(NULL, 0, &dwLen); BYTE *pBuff = new BYTE [dwLen]; if (pBuff) { CDeleteMe d (pBuff); DWORD dwLen1; hr = pInt->GetObjectMemory(pBuff, dwLen, &dwLen1); if (SUCCEEDED(hr)) { hr = CSQLExecProcedure::InsertBlobData(pConn, dClassId, dObjectId, dwPropId4, pBuff, 0, dwLen); } } else hr = WBEM_E_OUT_OF_MEMORY; pInt->Release(); } } } } return hr; } //*************************************************************************** // // CSQLExecProcedure::DeleteUncommittedEvents // //*************************************************************************** HRESULT CSQLExecProcedure::DeleteUncommittedEvents (CSQLConnection *pConn, LPCWSTR lpGUID, CSchemaCache *pCache, CObjectCache *pObjCache) { HRESULT hr = WBEM_S_NO_ERROR; // Delete all events by GUID // The simplest thing to do is to scan IndexStringData // for this GUID and delete each object that way INDEXDATA id; JET_TABLEID tableid; DWORD dwPos; SQLIDs ids; SQL_ID dClassId; hr = pCache->GetClassID(L"__UncommittedEvent", 1, dClassId); // Find all objects that match this GUID... hr = GetFirst_IndexDataString(pConn, (LPWSTR)lpGUID, id, tableid, dwPos); while (SUCCEEDED(hr)) { ids.push_back(id.dObjectId); // Clean up object cache for each event pObjCache->DeleteObject(id.dObjectId); hr = GetNext_IndexData(pConn, tableid, dwPos, id); } // Delete 'em... for (int i = 0; i < ids.size(); i++) { OBJECTMAP oj; hr = GetFirst_ObjectMap(pConn, ids.at(i), oj); if (oj.dClassId == dClassId) { oj.Clear(); hr = DeleteObjectMap(pConn, ids.at(i)); if (FAILED(hr)) break; } oj.Clear(); } return hr; } //*************************************************************************** // // CSQLExecProcedure::CommitEvents // //*************************************************************************** HRESULT CSQLExecProcedure::CommitEvents(CSQLConnection *pConn,_IWmiCoreServices *pESS, LPCWSTR lpRoot, LPCWSTR lpGUID, CSchemaCache *pCache, CObjectCache *pObjCache) { HRESULT hr = WBEM_S_NO_ERROR; // Enumerate event objects, // fire an event for each (distinguishing classes, instances, and namespaces, // and creation, deletion, modification) // Delete each event. INDEXDATA id; JET_TABLEID tableid; DWORD dwPos; SQLIDs ids; SQL_ID dClassId; hr = pCache->GetClassID(L"__UncommittedEvent", 1, dClassId); // Find all objects that match this GUID... hr = GetFirst_IndexDataString(pConn, (LPWSTR)lpGUID, id, tableid, dwPos); while (SUCCEEDED(hr)) { ids.push_back(id.dObjectId); // Clean up object cache for each event pObjCache->DeleteObject(id.dObjectId); hr = GetNext_IndexData(pConn, tableid, dwPos, id); } // Fire an event, and delete the object... for (int i = 0; i < ids.size(); i++) { long lType = 0; _bstr_t sNamespace; _bstr_t sClassName; DWORD dwNumObjs = 1; _IWmiObject **pObjs = NULL; _IWmiObject *pOldObj = NULL; _IWmiObject *pNewObj = NULL; LPWSTR lpNewNs = NULL; OBJECTMAP oj; hr = GetFirst_ObjectMap(pConn, ids.at(i), oj); if (SUCCEEDED(hr)) { if (oj.dClassId != dClassId) { oj.Clear(); continue; } // Extract the data from the tables. // OldObject, NewObject, ClassName and NamespaceName // ================================================= static DWORD dwPropId1 = 0, dwPropId2 = 0, dwPropId3 = 0, dwPropId4 = 0; if (!dwPropId1) { if (SUCCEEDED(hr)) { hr = pCache->GetPropertyID(L"NamespaceName", dClassId, 0, REPDRVR_IGNORE_CIMTYPE, dwPropId1); hr = pCache->GetPropertyID(L"ClassName", dClassId, 0, REPDRVR_IGNORE_CIMTYPE, dwPropId2); hr = pCache->GetPropertyID(L"OldObject", dClassId, 0, REPDRVR_IGNORE_CIMTYPE, dwPropId3); hr = pCache->GetPropertyID(L"NewObject", dClassId, 0, REPDRVR_IGNORE_CIMTYPE, dwPropId4); } } CLASSDATA cd; hr = GetFirst_ClassData(pConn, ids.at(i), cd, dwPropId1); if (SUCCEEDED(hr)) { sNamespace = cd.sPropertyStringValue; } cd.Clear(); hr = GetFirst_ClassData(pConn, ids.at(i), cd, dwPropId2); if (SUCCEEDED(hr)) { sClassName = cd.sPropertyStringValue; } cd.Clear(); CLASSIMAGES ci; hr = GetFirst_ClassImages(pConn, ids.at(i), ci); while (SUCCEEDED(hr)) { if (ci.iPropertyId == dwPropId3) ConvertBlobToObject(NULL, ci.pBuffer, ci.dwBufferLen, &pOldObj); else if (ci.iPropertyId == dwPropId4) ConvertBlobToObject(NULL, ci.pBuffer, ci.dwBufferLen, &pNewObj); hr = GetNext_ClassImages(pConn, ci); } ci.Clear(); // Namespace must be formatted with \\.\lpRoot\... // Unless the namespace is root, and then we // have to strip off the beginning... // =============================================== lpNewNs = new wchar_t [wcslen(sNamespace) + 50]; if (lpNewNs) { swprintf(lpNewNs, L"\\\\.\\%s\\%s", lpRoot, (LPCWSTR)sNamespace); } } CDeleteMe d4 (lpNewNs); // Determine what type of event this is: // Namespace | Class | Instance // Creation | Modification | Deletion // ===================================== if (!pNewObj && pOldObj) { pObjs = new _IWmiObject * [dwNumObjs]; if (pObjs) { pObjs[0] = pOldObj; LPWSTR lpGenus = GetPropertyVal(L"__Genus", pOldObj); CDeleteMe d (lpGenus); if (!wcscmp(lpGenus, L"1")) lType = WBEM_EVENTTYPE_ClassDeletion; else { if (IsDerivedFrom(pOldObj, L"__Namespace")) lType = WBEM_EVENTTYPE_NamespaceDeletion; else lType = WBEM_EVENTTYPE_InstanceDeletion; } } else hr = WBEM_E_OUT_OF_MEMORY; } else if (!pOldObj && pNewObj) { pObjs = new _IWmiObject *[dwNumObjs]; if (pObjs) { pObjs[0] = pNewObj; LPWSTR lpGenus = GetPropertyVal(L"__Genus", pNewObj); CDeleteMe d (lpGenus); if (!wcscmp(lpGenus, L"1")) lType = WBEM_EVENTTYPE_ClassCreation; else { if (IsDerivedFrom(pNewObj, L"__Namespace")) lType = WBEM_EVENTTYPE_NamespaceCreation; else lType = WBEM_EVENTTYPE_InstanceCreation; } } else hr = WBEM_E_OUT_OF_MEMORY; } else { dwNumObjs = 2; pObjs = new _IWmiObject *[dwNumObjs]; if (pObjs) { pObjs[0] = pOldObj; pObjs[1] = pNewObj; LPWSTR lpGenus = GetPropertyVal(L"__Genus", pNewObj); CDeleteMe d (lpGenus); if (!wcscmp(lpGenus, L"1")) lType = WBEM_EVENTTYPE_ClassModification; else { if (IsDerivedFrom(pOldObj, L"__Namespace")) lType = WBEM_EVENTTYPE_NamespaceModification; else lType = WBEM_EVENTTYPE_InstanceModification; } } else hr = WBEM_E_OUT_OF_MEMORY; } // Deliver the event... // ==================== pESS->DeliverIntrinsicEvent(lpNewNs, lType, NULL, sClassName, lpGUID, dwNumObjs, pObjs); delete pObjs; if (pOldObj) pOldObj->Release(); if (pNewObj) pNewObj->Release(); oj.Clear(); hr = DeleteObjectMap(pConn, ids.at(i)); if (FAILED(hr)) break; } return hr; } //*************************************************************************** // // CSQLExecProcedure::UpdateClassBlob // //*************************************************************************** HRESULT CSQLExecProcedure::UpdateClassBlob (CSQLConnection *pConn, SQL_ID dClassId, _IWmiObject *pObj) { HRESULT hr = WBEM_S_NO_ERROR; BYTE buff[128]; DWORD dwLen = 0; hr = pObj->Unmerge(0, 128, &dwLen, &buff); if (dwLen > 0) { BYTE *pBuff = new BYTE [dwLen]; if (pBuff) { CDeleteMe r2 (pBuff); DWORD dwLen1; hr = pObj->Unmerge(0, dwLen, &dwLen1, pBuff); if (SUCCEEDED(hr)) { CLASSMAP cd; hr = GetFirst_ClassMap(pConn, dClassId, cd); if (SUCCEEDED(hr)) { delete cd.pClassBuffer; cd.pClassBuffer = pBuff; cd.dwBufferLen = dwLen; hr = UpdateClassMap(pConn, cd); } } } else hr = WBEM_E_OUT_OF_MEMORY; } return hr; } //*************************************************************************** // // CWmiDbSession::LoadSchemaCache // //*************************************************************************** HRESULT CWmiDbSession::LoadSchemaCache () { HRESULT hr = WBEM_S_NO_ERROR; // This needs to load the cache with all class, property, // and namespace data. We are going to call three straight // select queries and grab the columns. // ========================================================== DWORD dwNumRows; CSQLConnection *pConn = NULL; if (m_pController) hr = GetSQLCache()->GetConnection(&pConn); if (SUCCEEDED(hr) && pConn) { // Enumerate scopes. // ================= SCOPEMAP sm; OBJECTMAP oj; CLASSIMAGES ci; DWORD dwSecurity; hr = OpenEnum_ScopeMap(pConn, sm); while (SUCCEEDED(hr)) { hr = GetFirst_ObjectMap(pConn, sm.dObjectId, oj); hr = GetSchemaCache()->AddNamespace (sm.sScopePath, sm.sScopePath, sm.dObjectId, sm.dParentId, oj.dClassId); oj.Clear(); if (FAILED(hr)) break; hr = GetNext_ScopeMap(pConn, sm); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; // Enumerate system classes. if (FAILED(LoadClassInfo(pConn, L"meta_class", 0, FALSE))) goto Exit; if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; // IDs with security descriptors GetSchemaCache()->GetPropertyID(L"__SECURITY_DESCRIPTOR", 1, 0, REPDRVR_IGNORE_CIMTYPE, dwSecurity); hr = GetFirst_ClassImagesByPropertyId(pConn, dwSecurity, ci); while (SUCCEEDED(hr)) { ((CWmiDbController *)m_pController)->AddSecurityDescriptor(ci.dObjectId); hr = GetNext_ClassImages(pConn, ci); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; } Exit: if (m_pController) GetSQLCache()->ReleaseConnection(pConn, hr, IsDistributed()); return hr; } //*************************************************************************** // // GetSuperClassInfo // //*************************************************************************** HRESULT GetSuperClassInfo(CSQLConnection *pConn, CSchemaCache *pCache, SQL_ID dClassId, BOOL &bKeyless, SQLIDs *pLockedIDs) { HRESULT hr = WBEM_S_NO_ERROR; CLASSMAP cd; OBJECTMAP oj; SQL_ID dSuperClass = 0; hr = GetFirst_ClassMap(pConn, dClassId, cd); if (SUCCEEDED(hr)) { dSuperClass = cd.dSuperClassId; pCache->LockDynasty(dSuperClass); pLockedIDs->push_back(dSuperClass); hr = GetFirst_ObjectMap(pConn, dClassId, oj); if (SUCCEEDED(hr)) { //DEBUGTRACE((LOG_WBEMCORE, "GetSuperClassInfo %S\n", cd.sClassName)); if (oj.iObjectFlags & REPDRVR_FLAG_ABSTRACT || oj.iObjectFlags & REPDRVR_FLAG_UNKEYED) bKeyless = TRUE; hr = pCache->AddClassInfo(cd.dClassId, cd.sClassName, cd.dSuperClassId, cd.dDynastyId, oj.dObjectScopeId, oj.sObjectKey, oj.iObjectFlags); if (SUCCEEDED(hr)) { hr = LoadSchemaProperties (pConn, pCache, dClassId); if (SUCCEEDED(hr) && dSuperClass && dSuperClass != 1) hr = GetSuperClassInfo(pConn, pCache, dSuperClass, bKeyless, pLockedIDs); } } cd.Clear(); oj.Clear(); } return hr; } //*************************************************************************** // // GetDerivedClassInfo // //*************************************************************************** HRESULT GetDerivedClassInfo(CSQLConnection *pConn, CSchemaCache *pCache, SQL_ID dClassId) { HRESULT hr = WBEM_S_NO_ERROR; SQLIDs ids; CLASSMAP cd; OBJECTMAP oj; SQL_ID dClass = 0; if (dClassId != 1) { hr = GetFirst_ClassMapBySuperClass(pConn, dClassId, cd); while (SUCCEEDED(hr)) { ids.push_back(cd.dClassId); hr = GetNext_ClassMap(pConn, cd); } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; for (int i = 0; i < ids.size(); i++) { dClass = ids.at(i); if (!pCache->Exists(dClass)) { hr = GetFirst_ClassMap(pConn, dClass, cd); hr = GetFirst_ObjectMap(pConn, dClass, oj); if (SUCCEEDED(hr)) { //DEBUGTRACE((LOG_WBEMCORE, "GetDerivedClassInfo %S\n", cd.sClassName)); hr = pCache->AddClassInfo(cd.dClassId, cd.sClassName, cd.dSuperClassId, cd.dDynastyId, oj.dObjectScopeId, oj.sObjectKey, oj.iObjectFlags); if (SUCCEEDED(hr)) { hr = LoadSchemaProperties (pConn, pCache, dClass); if (SUCCEEDED(hr)) hr = GetDerivedClassInfo(pConn, pCache, dClass); } } cd.Clear(); oj.Clear(); } } } return hr; } //*************************************************************************** // // CWmiDbSession::LoadClassInfo // //*************************************************************************** HRESULT CWmiDbSession::LoadClassInfo (CSQLConnection *_pConn, SQL_ID dClassId, BOOL bDeep) { HRESULT hr = WBEM_S_NO_ERROR; BOOL bRelease = FALSE; CSQLConnection *pConn = _pConn; _WMILockit lkt(GetCS()); DWORD dwSize = GetSchemaCache()->GetTotalSize(); DWORD dwMax = GetSchemaCache()->GetMaxSize(); int i = 0; if (dwMax <= dwSize) { DEBUGTRACE((LOG_WBEMCORE, "Repository schema cache has exceeded limit of %ld bytes (%ld). Resizing...\n", dwMax, dwSize)); // We do this here, so we ensure that *only* entire dynasties // get loaded. Its OK if we exceed the cache as long as // everything in the cache is in use. hr = GetSchemaCache()->ResizeCache(); } GetSchemaCache()->LockDynasty(dClassId); m_Dynasties[GetCurrentThreadId()].push_back(dClassId); // Check if this exists in the cache. // If so, stop now. //if (GetSchemaCache()->Exists(dClassId)) // return WBEM_S_NO_ERROR; if (!pConn && m_pController) { hr = GetSQLCache()->GetConnection(&pConn, FALSE, IsDistributed()); if (SUCCEEDED(hr)) bRelease = TRUE; else return hr; } // Now get all derived classes, and all parent classes. // ==================================================== BOOL bKeyless = FALSE; hr = GetSuperClassInfo(pConn, GetSchemaCache(), dClassId, bKeyless, &m_Dynasties[GetCurrentThreadId()]); if (SUCCEEDED(hr) && (!bKeyless || bDeep)) hr = GetDerivedClassInfo(pConn, GetSchemaCache(), dClassId); if (bRelease && m_pController) GetSQLCache()->ReleaseConnection(pConn); return hr; } //*************************************************************************** // // CWmiDbSession::LoadClassInfo // //*************************************************************************** HRESULT CWmiDbSession::LoadClassInfo (CSQLConnection *_pConn, LPCWSTR lpDynasty, SQL_ID dScopeId, BOOL bDeep) { HRESULT hr = WBEM_S_NO_ERROR; DWORD dwSize = GetSchemaCache()->GetTotalSize(); DWORD dwMax = GetSchemaCache()->GetMaxSize(); SQLIDs ids; int i = 0; if (dwMax <= dwSize) { DEBUGTRACE((LOG_WBEMCORE, "Repository schema cache has exceeded limit of %ld bytes (%ld). Resizing...\n", dwMax, dwSize)); // We do this here, so we ensure that *only* entire dynasties // get loaded. Its OK if we exceed the cache as long as // everything in the cache is in use. hr = GetSchemaCache()->ResizeCache(); } BOOL bRelease = FALSE; CSQLConnection *pConn = _pConn; if (!pConn && m_pController) { hr = GetSQLCache()->GetConnection(&pConn, FALSE, IsDistributed()); if (SUCCEEDED(hr)) bRelease = TRUE; else return hr; } CLASSMAP cd; OBJECTMAP oj; if (!lpDynasty) { if ((GetSchemaCache()->Exists(1))) return WBEM_S_NO_ERROR; hr = OpenEnum_ClassMap(pConn, cd); while (SUCCEEDED(hr)) { if (cd.dSuperClassId == 0) ids.push_back(cd.dClassId); hr = GetNext_ClassMap(pConn, cd); } for (i = 0; i < ids.size(); i++) { hr = GetFirst_ClassMap(pConn, ids.at(i), cd); hr = GetFirst_ObjectMap(pConn, ids.at(i), oj); if (SUCCEEDED(hr)) hr = GetSchemaCache()->AddClassInfo(oj.dObjectId, cd.sClassName, cd.dSuperClassId, cd.dDynastyId, oj.dObjectScopeId, oj.sObjectKey, oj.iObjectFlags); cd.Clear(); oj.Clear(); if (FAILED(hr)) break; hr = LoadSchemaProperties (pConn, &((CWmiDbController *)m_pController)->SchemaCache, ids.at(i)); if (FAILED(hr)) break; } } else { // We need to find all classes derived from // this dynasty. SQL_ID dDynasty = 0; BOOL bFound = FALSE; hr = GetFirst_ClassMapByName(pConn, lpDynasty, cd); while (SUCCEEDED(hr)) { hr = GetFirst_ObjectMap(pConn, cd.dClassId, oj); if (!oj.dObjectScopeId || oj.dObjectScopeId == dScopeId) { oj.Clear(); cd.Clear(); bFound = TRUE; dDynasty = cd.dClassId; break; } oj.Clear(); hr = GetNext_ClassMap(pConn, cd); } if (bFound) hr = LoadClassInfo(pConn, dDynasty, bDeep); else hr = WBEM_E_NOT_FOUND; } if (bRelease && m_pController) GetSQLCache()->ReleaseConnection(pConn); return hr; } //*************************************************************************** // // CWmiDbSession::ExecQuery // //*************************************************************************** HRESULT STDMETHODCALLTYPE CWmiDbSession::ExecQuery( /* [in] */ IWmiDbHandle __RPC_FAR *pScope, /* [in] */ IWbemQuery __RPC_FAR *pQuery, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwHandleType, /* [out] */ DWORD *dwMessageFlags, /* [out] */ IWmiDbIterator __RPC_FAR *__RPC_FAR *pQueryResult) { HRESULT hr = WBEM_S_NO_ERROR; if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN; if (dwHandleType == WMIDB_HANDLE_TYPE_INVALID || !pQuery || !pQueryResult || !pScope) return WBEM_E_INVALID_PARAMETER; if (dwHandleType & ~WMIDB_HANDLE_TYPE_COOKIE &~WMIDB_HANDLE_TYPE_VERSIONED &~WMIDB_HANDLE_TYPE_PROTECTED &~WMIDB_HANDLE_TYPE_EXCLUSIVE &~ WMIDB_HANDLE_TYPE_WEAK_CACHE &~WMIDB_HANDLE_TYPE_STRONG_CACHE &~ WMIDB_HANDLE_TYPE_NO_CACHE &~WMIDB_HANDLE_TYPE_SUBSCOPED) return WBEM_E_INVALID_PARAMETER; if (dwFlags & ~WMIDB_FLAG_QUERY_DEEP &~WMIDB_FLAG_QUERY_SHALLOW & ~WBEM_FLAG_USE_SECURITY_DESCRIPTOR) return WBEM_E_INVALID_PARAMETER; try { if (dwMessageFlags) *dwMessageFlags = WBEM_REQUIREMENTS_STOP_POSTFILTER; DWORD dwOpenTable = 0; SQL_ID dClassId = 0; JET_TABLEID tableid = 0; CSQLConnection *pConn = NULL; // Obtain a database connection if (m_pController) hr = GetSQLCache()->GetConnection(&pConn, FALSE, IsDistributed()); if (FAILED(hr) || !pQuery || !pScope) { hr = WBEM_E_INVALID_PARAMETER; } else { BOOL bDeleteQuery = FALSE; SQL_ID dwNsId = 0; IWbemClassObject *pTemp = NULL; CESETokens *pToks = NULL; int iLastPos = 0; BOOL bEnum = FALSE; BOOL bWQL = TRUE; BOOL bClasses = FALSE; int iStartCrit = 0; HRESULT hrMatch = WBEM_S_NO_ERROR; dwNsId = ((CWmiDbHandle *)pScope)->m_dObjectId; SQL_ID dScopeClassId = ((CWmiDbHandle *)pScope)->m_dClassId; SQL_ID dSuperScope = ((CWmiDbHandle *)pScope)->m_dScopeId; DWORD dwScopeType = ((CWmiDbHandle *)pScope)->m_dwHandleType ; if (pScope && !(dwScopeType & WMIDB_HANDLE_TYPE_CONTAINER)) hr=VerifyObjectSecurity (pConn, dwNsId, dScopeClassId, dSuperScope, 0, WBEM_ENABLE); SWbemAssocQueryInf *pNode = NULL; hr = pQuery->GetAnalysis(WMIQ_ANALYSIS_ASSOC_QUERY, 0, (void **)&pNode); if (FAILED(hr)) { BOOL bIndexCols = FALSE, bHierarchy = 0, bSuperSet = FALSE; // Since ESE has no query engine, we need to: // Parse the query // Figure out which index to use and prefilter // slap the parsed output onto the iterator as a post-filter. // if the query includes elements that cannot be handled in memory, // we need to return WBEM_E_INVALID_QUERY or WBEM_E_PROVIDER_NOT_CAPABLE // ================================================================ CESEBuilder bldr(&((CWmiDbController *)m_pController)->SchemaCache, this, pConn); hr = bldr.FormatSQL(((CWmiDbHandle *)pScope)->m_dObjectId, ((CWmiDbHandle *)pScope)->m_dClassId, ((CWmiDbHandle *)pScope)->m_dScopeId, pQuery, &pToks, dwFlags, ((CWmiDbHandle *)pScope)->m_dwHandleType, &dClassId, &bHierarchy, &bIndexCols, &bSuperSet, &bDeleteQuery); // Make sure we have access to the target class. // We won't check locks at this point, since that will // be the iterator's job. // If we can't analyze this query, // we certainly can't delete the results. if (bDeleteQuery && bSuperSet) hr = WBEM_E_NOT_SUPPORTED; if (!pToks && SUCCEEDED(hr)) hr = WBEM_E_INVALID_QUERY; if (SUCCEEDED(hr)) { if (dwMessageFlags) *dwMessageFlags = (bSuperSet ? WBEM_REQUIREMENTS_START_POSTFILTER : WBEM_REQUIREMENTS_STOP_POSTFILTER); if (SUCCEEDED(hr)) { int i; BOOL bEnumSubClass = TRUE; SQL_ID dClassCrit = 0, dSuperClassCrit = 0, dDynastyCrit = 0; if (dClassId == 1) // meta_class - we only want classes { bClasses = TRUE; bEnumSubClass = FALSE; // * __Class = ... => Limit to single class // * __SuperClass = => Prescan on SuperClassId // * __Dynasty = => Prescan on DynastyId // * __this isa => Enum subclasses + list criteria. DWORD dwClassPropID = 0, dwSuperClassPropID = 0, dwDynastyPropID = 0; DWORD dwDerivationPropID = 0; BOOL bClassCrit = FALSE, bSuperClassCrit = FALSE, bDynastyCrit = FALSE; GetSchemaCache()->GetPropertyID(L"__Class", 1, 0, REPDRVR_IGNORE_CIMTYPE, dwClassPropID); GetSchemaCache()->GetPropertyID(L"__SuperClass", 1, 0, REPDRVR_IGNORE_CIMTYPE, dwSuperClassPropID); GetSchemaCache()->GetPropertyID(L"__Dynasty", 1, 0, REPDRVR_IGNORE_CIMTYPE, dwDynastyPropID); GetSchemaCache()->GetPropertyID(L"__Derivation", 1, 0, REPDRVR_IGNORE_CIMTYPE, dwDerivationPropID); BOOL bFound = FALSE; for (i = 0; i < pToks->GetNumTokens(); i++) { ESEToken *pTok = pToks->GetToken(i); if (pTok && pTok->tokentype == ESE_EXPR_TYPE_EXPR) { if (((ESEWQLToken *)pTok)->tokentype == ESE_EXPR_TYPE_OR || ((ESEWQLToken *)pTok)->tokentype == ESE_EXPR_TYPE_NOT) { bClassCrit = 0; bSuperClassCrit = 0; bDynastyCrit = 0; break; } if (((ESEWQLToken *)pTok)->optype == WQL_TOK_EQ) { SQL_ID dClassId2 = 0, dDynasty = 0; if (wcslen((((ESEWQLToken *)pTok)->Value.sValue))) { hr = GetSchemaCache()->GetClassID (((ESEWQLToken *)pTok)->Value.sValue, dwNsId, dClassId2, &dDynasty); } if ((((ESEWQLToken *)pTok)->dPropertyId == dwClassPropID)) { bClassCrit = TRUE; dClassCrit = dClassId2; } else if ((((ESEWQLToken *)pTok)->dPropertyId == dwSuperClassPropID)) { bSuperClassCrit = TRUE; dSuperClassCrit = dClassId2; } else if ((((ESEWQLToken *)pTok)->dPropertyId == dwDynastyPropID)) { bDynastyCrit = TRUE; dDynastyCrit = dClassId2; } else if ((((ESEWQLToken *)pTok)->dPropertyId == dwDerivationPropID)) { bDynastyCrit = TRUE; dDynastyCrit = dDynasty; dClassId = dClassId2; if (dDynasty != dClassId2) { bEnumSubClass = TRUE; } } } } } pToks->SetIsMetaClass(TRUE); if (bClassCrit) { OBJECTMAP oj; hrMatch = GetFirst_ObjectMap(pConn, dClassCrit, oj); tableid = ((CESEConnection *)pConn)->GetTableID(L"ObjectMap"); dwOpenTable = OPENTABLE_OBJECTMAP; oj.Clear(); } else if (bSuperClassCrit) { CLASSMAP cm; if (!dSuperClassCrit) dSuperClassCrit = 1; hrMatch = GetFirst_ClassMapBySuperClass(pConn, dSuperClassCrit, cm); tableid = ((CESEConnection *)pConn)->GetTableID(L"ClassMap"); dwOpenTable = OPENTABLE_CLASSMAP; cm.Clear(); } else if (bDynastyCrit) { CLASSMAP cm; hrMatch = GetFirst_ClassMapByDynasty(pConn, dDynastyCrit, cm); tableid = ((CESEConnection *)pConn)->GetTableID(L"ClassMap"); dwOpenTable = OPENTABLE_CLASSMAP; cm.Clear(); } else // Scan all ClassMap { pToks->AddSysExpr(0, dClassId); CLASSMAP cm; hrMatch = OpenEnum_ClassMap(pConn, cm); tableid = ((CESEConnection *)pConn)->GetTableID(L"ClassMap"); dwOpenTable = OPENTABLE_CLASSMAP; cm.Clear(); } } if (bEnumSubClass) { // If we need to limit the classes by class ID // get the derived class list. // Disregard if this is meta_class - we're only // interested in returning classes. SQL_ID *pIDs = NULL; int iNumChildren = 0; GetSchemaCache()->GetDerivedClassList(dClassId, &pIDs, iNumChildren, FALSE); if (pIDs) { for (i = iNumChildren-1; i >= 0; i--) { SQL_ID d = pIDs[i]; pToks->AddSysExpr(0, d); } delete pIDs; } // Optimization for class with no children. if (!iNumChildren && pToks->IsMetaClass() && (dClassId != 1)) { CLASSMAP cm; hrMatch = GetFirst_ClassMap(pConn, dClassId, cm); tableid = ((CESEConnection *)pConn)->GetTableID(L"ClassMap"); dwOpenTable = OPENTABLE_CLASSMAP; cm.Clear(); } } if ( ((CWmiDbHandle *)pScope)->m_dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER) { CONTAINEROBJ co; hrMatch = GetFirst_ContainerObjs(pConn, ((CWmiDbHandle *)pScope)->m_dObjectId, co); co.Clear(); dwOpenTable = OPENTABLE_CONTAINEROBJS; tableid = ((CESEConnection *)pConn)->GetTableID(L"ContainerObjs"); } else { if (bIndexCols) { // Seek to property ID of first indexed criteria DWORD dwNumToks = pToks->GetNumTokens(); for (i = 0; i < dwNumToks; i++) { ESEToken *pTok = pToks->GetToken(i); if (pTok && pTok->tokentype == ESE_EXPR_TYPE_EXPR) { INDEXDATA id; iLastPos = i; DWORD dwPos = 0; ESEWQLToken *pTok2 = (ESEWQLToken *)pTok; if (pTok2->bIndexed) { switch(pTok2->Value.valuetype) { case ESE_VALUE_TYPE_SQL_ID: SetupIndexDataAccessor(pConn, WMIDB_STORAGE_NUMERIC, dwPos, NULL); tableid = ((CESEConnection *)pConn)->GetTableID(L"IndexNumericData"); hrMatch = GetFirst_IndexDataByProperty(pConn, pTok2->dPropertyId, id, tableid, SQL_POS_INDEXNUMERIC); dwOpenTable = OPENTABLE_INDEXNUMERIC; id.Clear(); break; case ESE_VALUE_TYPE_STRING: SetupIndexDataAccessor(pConn, WMIDB_STORAGE_STRING, dwPos, NULL); tableid = ((CESEConnection *)pConn)->GetTableID(L"IndexStringData"); hrMatch = GetFirst_IndexDataByProperty(pConn, pTok2->dPropertyId, id, tableid, SQL_POS_INDEXSTRING); dwOpenTable = OPENTABLE_INDEXSTRING; id.Clear(); break; case ESE_VALUE_TYPE_REAL: SetupIndexDataAccessor(pConn, WMIDB_STORAGE_REAL, dwPos, NULL); tableid = ((CESEConnection *)pConn)->GetTableID(L"IndexRealData"); hrMatch = GetFirst_IndexDataByProperty(pConn, pTok2->dPropertyId, id, tableid, SQL_POS_INDEXREAL); dwOpenTable = OPENTABLE_INDEXREAL; id.Clear(); break; case ESE_VALUE_TYPE_REF: SetupIndexDataAccessor(pConn, WMIDB_STORAGE_REFERENCE, dwPos, NULL); tableid = ((CESEConnection *)pConn)->GetTableID(L"IndexRefData"); hrMatch = GetFirst_IndexDataByProperty(pConn, pTok2->dPropertyId, id, tableid, SQL_POS_INDEXREF); dwOpenTable = OPENTABLE_INDEXREF; id.Clear(); break; default: break; } if (dwOpenTable) break; } } } } if (!dwOpenTable) { dwOpenTable = OPENTABLE_OBJECTMAP; OBJECTMAP oj; // Find the first class that matches. DWORD dwNumToks = pToks->GetNumTokens(); for (i = 0; i < dwNumToks; i++) { ESEToken *pTok = pToks->GetToken(i); if (pTok->tokentype == ESE_EXPR_TYPE_EXPR) { ESEWQLToken *pTok2 = (ESEWQLToken *)pTok; if (pTok2->Value.valuetype == ESE_VALUE_TYPE_SYSPROP) { if (pTok2->dClassId) { hrMatch = GetFirst_ObjectMapByClass(pConn, pTok2->dClassId, oj); if (SUCCEEDED(hrMatch)) { oj.Clear(); iLastPos = i; break; } oj.Clear(); } } } } tableid = ((CESEConnection *)pConn)->GetTableID(L"ObjectMap"); } } } } } else { SQL_ID dObjId = 0; CESEBuilder bldr(&((CWmiDbController *)m_pController)->SchemaCache, this, pConn); if (SUCCEEDED(hr)) { // Get dObjId. SQL_ID dAssocClassId = 0, dResultClassId = 0; IWbemPath *pPath = NULL; hr = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER, IID_IWbemPath, (LPVOID *) &pPath); BOOL bIsClass = FALSE; if (SUCCEEDED(hr)) { CReleaseMe r (pPath); pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, pNode->m_pszPath); IWmiDbHandle *pTemp = NULL; hr = GetObject(pScope, pPath, dwFlags, WMIDB_HANDLE_TYPE_COOKIE, &pTemp); if (SUCCEEDED(hr)) { // We need rudimentary tempQL support BOOL bSuperSet = FALSE; dObjId = ((CWmiDbHandle *)pTemp)->m_dObjectId; bIsClass = ((CWmiDbHandle *)pTemp)->m_dClassId == 1 ? TRUE: FALSE; pTemp->Release(); hr = bldr.FormatSQL(((CWmiDbHandle *)pScope)->m_dObjectId, ((CWmiDbHandle *)pScope)->m_dClassId, ((CWmiDbHandle *)pScope)->m_dScopeId, dObjId, pNode->m_pszResultClass, pNode->m_pszAssocClass, pNode->m_pszRole, pNode->m_pszResultRole, pNode->m_pszRequiredQualifier, pNode->m_pszRequiredAssocQualifier, pNode->m_uFeatureMask, &pToks, dwFlags, ((CWmiDbHandle *)pScope)->m_dwHandleType, &dAssocClassId, &dResultClassId, &bSuperSet); bWQL = FALSE; if (!pToks && SUCCEEDED(hr)) hr = WBEM_E_INVALID_QUERY; if (SUCCEEDED(hr)) { if (dwMessageFlags) { *dwMessageFlags = (bSuperSet ? WBEM_REQUIREMENTS_START_POSTFILTER : WBEM_REQUIREMENTS_STOP_POSTFILTER); if (pNode->m_uFeatureMask & (QUERY_TYPE_SCHEMA_ONLY + QUERY_TYPE_CLASSDEFS_ONLY)) *dwMessageFlags = TRUE; } hr=VerifyClassSecurity (pConn, dObjId, WBEM_ENABLE); if (SUCCEEDED(hr) && dAssocClassId) { hr=VerifyClassSecurity (pConn, dAssocClassId, WBEM_ENABLE); } if (SUCCEEDED(hr) && dResultClassId) { hr=VerifyClassSecurity(pConn, dResultClassId, WBEM_ENABLE); } } } } pQuery->FreeMemory(pNode); if (SUCCEEDED(hr)) { if (!bIsClass) { // Use the target object, REFID INDEXDATA is; DWORD dwPos = 0; hrMatch = GetFirst_IndexDataRef(pConn, dObjId, is, tableid, dwPos); dwOpenTable = OPENTABLE_INDEXREF; is.Clear(); tableid = ((CESEConnection *)pConn)->GetTableID(L"IndexRefData"); } else { // We need to examine each class, and see if it contains // an association or reference to the target class. REFERENCEPROPERTIES pm; hrMatch = GetFirst_ReferencePropertiesByRef (pConn, dObjId, pm); dwOpenTable = OPENTABLE_REFPROPS; tableid = ((CESEConnection *)pConn)->GetTableID(L"ReferenceProperties"); if (dwMessageFlags) *dwMessageFlags = WBEM_REQUIREMENTS_START_POSTFILTER; } } } } // Construct and return the iterator. // This contains the open SQL connection positioned // on the first valid row if (SUCCEEDED(hr)) { DWORD dwRows; CWmiESEIterator *pNew = new CWmiESEIterator; if (pNew) { AddRef_Lock(); pNew->m_pSession = this; pNew->m_pConn = pConn; pNew->m_pToks = pToks; if (SUCCEEDED(hrMatch)) pNew->m_dwOpenTable = dwOpenTable; else pNew->m_dwOpenTable = 0; pNew->m_tableid = tableid; pNew->m_iLastPos = iLastPos; if (bEnum) pNew->m_iStartPos = iStartCrit; else pNew->m_iStartPos = 0; pNew->m_bEnum = bEnum; pNew->m_bWQL = bWQL; pNew->m_bClasses = bClasses; pNew->AddRef(); AddRef(); // The iterator releases us on its own release // If this was a delete query, // enumerate the results, and delete 'em if (bDeleteQuery) { hr = DeleteRows(pScope, pNew, IID_IWmiDbHandle); pNew->Release(); *pQueryResult = NULL; } // select query. Give them the iterator else if (pQueryResult) { *pQueryResult = (IWmiDbIterator *)pNew; } } else { hr = WBEM_E_OUT_OF_MEMORY; } } else delete pToks; } // If we failed, we need to release the connection // Otherwise, it will be attached to the iterator, // and will be released when the last result row has been returned if (FAILED(hr) && pConn && m_pController) GetSQLCache()->ReleaseConnection(pConn); } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::ExecQuery\n")); hr = WBEM_E_CRITICAL_ERROR; } return hr; } //*************************************************************************** // // CWmiDbSession::Enumerate // //*************************************************************************** HRESULT STDMETHODCALLTYPE CWmiDbSession::Enumerate( /* [in] */ IWmiDbHandle __RPC_FAR *pScope, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwRequestedHandleType, /* [out] */ IWmiDbIterator __RPC_FAR *__RPC_FAR *ppQueryResult) { HRESULT hr = WBEM_S_NO_ERROR; if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN; if (dwRequestedHandleType == WMIDB_HANDLE_TYPE_INVALID || !pScope) return WBEM_E_INVALID_PARAMETER; if (dwRequestedHandleType & ~WMIDB_HANDLE_TYPE_COOKIE &~WMIDB_HANDLE_TYPE_VERSIONED &~WMIDB_HANDLE_TYPE_PROTECTED &~WMIDB_HANDLE_TYPE_EXCLUSIVE &~ WMIDB_HANDLE_TYPE_WEAK_CACHE &~WMIDB_HANDLE_TYPE_STRONG_CACHE &~ WMIDB_HANDLE_TYPE_NO_CACHE &~WMIDB_HANDLE_TYPE_SUBSCOPED &~WMIDB_HANDLE_TYPE_CONTAINER &~ WMIDB_HANDLE_TYPE_SCOPE) return WBEM_E_INVALID_PARAMETER; try { { _WMILockit lkt(GetCS()); if (!((CWmiDbController *)m_pController)->m_bCacheInit) { hr = LoadSchemaCache(); if (SUCCEEDED(hr)) ((CWmiDbController *)m_pController)->m_bCacheInit = TRUE; else return hr; } } JET_TABLEID tableid = 0; MappedProperties *pProps; DWORD dwNumProps; BOOL bHierarchy = FALSE; SQL_ID dwNsId = 0, dClassId = 0; _bstr_t sPath; int iNumRows = 0; IWbemClassObject *pTemp = NULL; if (pScope) { // CVADAI: This is a container, not a scope, so this // info won't be cached. dwNsId = ((CWmiDbHandle *)pScope)->m_dObjectId; dClassId = ((CWmiDbHandle *)pScope)->m_dClassId; //SQL_ID dScopeId = ((CWmiDbHandle *)pScope)->m_dScopeId; //hr = VerifyObjectSecurity(dwNsId, dClassId, dScopeId, 0, WBEM_ENABLE); } if (SUCCEEDED(hr) && m_pController) { DWORD dwRows; IRowset *pRowset = NULL; CSQLConnection *pConn=NULL; hr = GetSQLCache()->GetConnection(&pConn, FALSE, IsDistributed()); if (SUCCEEDED(hr)) { // Here we need to do the equivalent enumeration based // on table or index scan, and return a custom iterator // Basically, we stuff the filter conditions on the iterator, // and return it. // ==================================================== DWORD dwOpenTable = 0; CESETokens *pToks = NULL; wchar_t sSQL [1024]; DWORD dwHandleType = ((CWmiDbHandle *)pScope)->m_dwHandleType; if (dClassId == INSTANCESCLASSID) { // ClassId = dwNsId AND // ObjectScopeId = dScopeId OBJECTMAP oj; SQL_ID dScopeId = ((CWmiDbHandle *)pScope)->m_dScopeId; hr = GetFirst_ObjectMapByClass(pConn, dwNsId, oj); oj.Clear(); if (SUCCEEDED(hr)) dwOpenTable = OPENTABLE_OBJECTMAP; tableid = ((CESEConnection *)pConn)->GetTableID(L"ObjectMap"); pToks = new CESETokens; if (pToks) pToks->AddSysExpr(dScopeId, dwNsId); else hr = WBEM_E_OUT_OF_MEMORY; } else if (dwHandleType & WMIDB_HANDLE_TYPE_CONTAINER) { // ContainerId = dContainerId (Use ContainerObjs) SQL_ID dContainerId = ((CWmiDbHandle *)pScope)->m_dObjectId; pToks = new CESETokens; if (pToks) { CONTAINEROBJ co; hr = GetFirst_ContainerObjs(pConn, dContainerId, co); if (SUCCEEDED(hr)) dwOpenTable = OPENTABLE_CONTAINEROBJS; co.Clear(); tableid = ((CESEConnection *)pConn)->GetTableID(L"ContainerObjs"); } else hr = WBEM_E_OUT_OF_MEMORY; } // Scope else { // ObjectScopeId = dwNsId OBJECTMAP oj; SQL_ID dScopeId = ((CWmiDbHandle *)pScope)->m_dObjectId; hr = GetFirst_ObjectMapByScope(pConn, dScopeId, oj); oj.Clear(); if (SUCCEEDED(hr)) dwOpenTable = OPENTABLE_OBJECTMAP; tableid = ((CESEConnection *)pConn)->GetTableID(L"ObjectMap"); pToks = new CESETokens; if (pToks) pToks->AddSysExpr(dScopeId, 0); else hr = WBEM_E_OUT_OF_MEMORY; } if (hr == WBEM_E_NOT_FOUND) hr = WBEM_S_NO_ERROR; // create the iterator, for consistency. if (SUCCEEDED(hr)) { CWmiESEIterator *pNew = new CWmiESEIterator; if (pNew) { *ppQueryResult = (IWmiDbIterator *)pNew; pNew->m_pConn = pConn; // Releasing the iterator will release this guy. pNew->m_pSession = this; pNew->m_pConn = pConn; pNew->m_pToks = pToks; pNew->m_dwOpenTable = dwOpenTable; pNew->m_tableid = tableid; pNew->AddRef(); AddRef(); } else { if (m_pController) GetSQLCache()->ReleaseConnection(pConn); hr = WBEM_E_OUT_OF_MEMORY; } } else { if (m_pController) GetSQLCache()->ReleaseConnection(pConn); hr = WBEM_E_OUT_OF_MEMORY; } } } } catch (...) { ERRORTRACE((LOG_WBEMCORE, "Fatal error in CWmiDbSession::Enumerate\n")); hr = WBEM_E_CRITICAL_ERROR; } return hr; } //*************************************************************************** // // CWmiDbSession::InsertArray // //*************************************************************************** HRESULT CWmiDbSession::InsertArray(CSQLConnection *pConn,IWmiDbHandle *pScope, SQL_ID dObjectId, SQL_ID dClassId, DWORD dwPropertyID, VARIANT &vValue, long lFlavor, DWORD dwRefID, LPCWSTR lpObjectKey , LPCWSTR lpPath , SQL_ID dScope, CIMTYPE ct ) { HRESULT hr = WBEM_S_NO_ERROR; IRowset *pIRowset = NULL; DWORD dwRows = 0; if (!m_pController || ((CWmiDbController *)m_pController)->m_dwCurrentStatus == WBEM_E_SHUTTING_DOWN) return WBEM_E_SHUTTING_DOWN; if (vValue.vt == VT_UNKNOWN) { BYTE *pBuff = NULL; DWORD dwLen = 0; IUnknown *pUnk = V_UNKNOWN (&vValue); if (pUnk) { _IWmiObject *pInt = NULL; hr = pUnk->QueryInterface(IID__IWmiObject, (void **)&pInt); if (SUCCEEDED(hr)) { pInt->GetObjectMemory(NULL, 0, &dwLen); pBuff = new BYTE [dwLen]; if (pBuff) { CDeleteMe d (pBuff); DWORD dwLen1; hr = pInt->GetObjectMemory(pBuff, dwLen, &dwLen1); if (SUCCEEDED(hr)) { hr = CSQLExecProcedure::InsertBlobData(pConn, dClassId, dObjectId, dwPropertyID, pBuff, dwRefID, dwLen); } } else hr = WBEM_E_OUT_OF_MEMORY; pInt->Release(); } } } else if (((vValue.vt & 0xFFF) == VT_UI1) || vValue.vt == VT_BSTR) { BYTE *pBuff = NULL; DWORD dwLen = 0; // Get the byte buffer out of the safearray. if ((vValue.vt & 0xFFF) == VT_UI1) GetByteBuffer(&vValue, &pBuff, dwLen); else // its a bstr. { dwLen = wcslen(vValue.bstrVal)*2+2; char * pTemp = new char[dwLen+1]; if (pTemp) { sprintf(pTemp, "%S", vValue.bstrVal); pBuff = (unsigned char *)pTemp; } else hr = WBEM_E_OUT_OF_MEMORY; } if (pBuff) { hr = CSQLExecProcedure::InsertBlobData (pConn, dClassId, dObjectId, dwPropertyID, pBuff, 0, dwLen); delete pBuff; } } else { bool bIsQfr = FALSE; DWORD dwFlags = 0; SQL_ID dClassID = 0; DWORD dwStorage = 0; hr = GetSchemaCache()->GetPropertyInfo (dwPropertyID, NULL, &dClassID, &dwStorage, NULL, &dwFlags); bIsQfr = (dwFlags & REPDRVR_FLAG_QUALIFIER) ? TRUE : FALSE; SAFEARRAY* psaArray = NULL; psaArray = V_ARRAY(&vValue); if (psaArray) { long i = 0; int iType = vValue.vt & 0xFF; VARIANT vTemp; VariantInit(&vTemp); long lLBound, lUBound; SafeArrayGetLBound(psaArray, 1, &lLBound); SafeArrayGetUBound(psaArray, 1, &lUBound); lUBound -= lLBound; lUBound += 1; InsertQfrValues *pQfr = NULL; int iPos = 0; pQfr = new InsertPropValues[lUBound]; if (!pQfr) return WBEM_E_OUT_OF_MEMORY; ct = ct & 0xFF; for (i = 0; i < lUBound; i++) { if (ct != CIM_OBJECT) { if (iType != VT_NULL && iType != VT_EMPTY) { hr = GetVariantFromArray(psaArray, i, iType, vTemp); LPWSTR lpVal = GetStr(vTemp); CDeleteMe r1(lpVal); VariantClear(&vTemp); if (FAILED(hr)) break; //if (wcslen(lpVal)) { pQfr[iPos].iPos = i; pQfr[iPos].iQfrID = dwRefID; pQfr[iPos].iPropID = dwPropertyID; pQfr[iPos].pRefKey = NULL; pQfr[iPos].bLong = false; pQfr[iPos].bIndexed = (dwFlags & (REPDRVR_FLAG_KEY + REPDRVR_FLAG_INDEXED)) ? TRUE : FALSE; pQfr[iPos].iStorageType = dwStorage; pQfr[iPos].dClassId = dClassID; pQfr[iPos].iFlavor = lFlavor; if (ct == CIM_REFERENCE) { pQfr[iPos].bIndexed = TRUE; // References are always keys LPWSTR lpTemp = NULL; IWbemPath *pPath = NULL; hr = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER, IID_IWbemPath, (LPVOID *) &pPath); CReleaseMe r8 (pPath); if (SUCCEEDED(hr)) { if (lpVal) { LPWSTR lpStrip = StripQuotes2 (lpVal); CDeleteMe d (lpStrip); pPath->SetText(WBEMPATH_CREATE_ACCEPT_ALL, lpStrip); hr = NormalizeObjectPathGet(pScope, pPath, &lpTemp, NULL, NULL, NULL, pConn); CDeleteMe r1(lpTemp); if (SUCCEEDED(hr)) { LPWSTR lpTemp2 = NULL; lpTemp2 = GetKeyString(lpStrip); CDeleteMe d (lpTemp2); pQfr[iPos].pRefKey = new wchar_t [21]; if (pQfr[iPos].pRefKey) swprintf(pQfr[iPos].pRefKey, L"%I64d", CRC64::GenerateHashValue(lpTemp2)); else hr = WBEM_E_OUT_OF_MEMORY; } else { hr = WBEM_S_NO_ERROR; // Strip off the root namespace prefix and generate the // pseudo-name. We have no way of knowing if they entered this // path correctly. LPWSTR lpTemp3 = StripUnresolvedName (lpStrip); CDeleteMe d2 (lpTemp3); LPWSTR lpTemp2 = NULL; lpTemp2 = GetKeyString(lpTemp3); CDeleteMe d (lpTemp2); pQfr[iPos].pRefKey = new wchar_t [21]; if (lpTemp2 && pQfr[iPos].pRefKey) swprintf(pQfr[iPos].pRefKey, L"%I64d", CRC64::GenerateHashValue(lpTemp2)); else hr = WBEM_E_OUT_OF_MEMORY; } pQfr[iPos].pValue = new wchar_t[wcslen(lpStrip)+1]; if (pQfr[iPos].pValue) wcscpy(pQfr[iPos].pValue,lpStrip); else hr = WBEM_E_OUT_OF_MEMORY; } else pQfr[iPos].pValue = NULL; } else break; } else { if (lpVal) { pQfr[iPos].pValue = new wchar_t[wcslen(lpVal)+1]; if (pQfr[iPos].pValue) wcscpy(pQfr[iPos].pValue,lpVal); else hr = WBEM_E_OUT_OF_MEMORY; } else pQfr[iPos].pValue = NULL; pQfr[iPos].pRefKey = NULL; } iPos++; } } } else { // Can't have default embedded object array values. if (lpPath) { hr = GetVariantFromArray(psaArray, i, iType, vTemp); IUnknown *pTemp = V_UNKNOWN(&vTemp); if (pTemp) { BYTE *pBuff = NULL; DWORD dwLen; _IWmiObject *pInt = NULL; hr = pTemp->QueryInterface(IID__IWmiObject, (void **)&pInt); if (SUCCEEDED(hr)) { pInt->GetObjectMemory(NULL, 0, &dwLen); pBuff = new BYTE [dwLen]; if (pBuff) { CDeleteMe d (pBuff); DWORD dwLen1; hr = pInt->GetObjectMemory(pBuff, dwLen, &dwLen1); if (SUCCEEDED(hr)) { hr = CSQLExecProcedure::InsertBlobData(pConn, dClassId, dObjectId, dwPropertyID, pBuff, i, dwLen); } } else hr = WBEM_E_OUT_OF_MEMORY; pInt->Release(); } else break; } } } } if (SUCCEEDED(hr)) hr = CSQLExecProcedure::InsertBatch (pConn, dObjectId, 0, 0, pQfr, iPos); // Finally clean up the upper array bounds // (if this array used to be bigger...) // ==================================== if (SUCCEEDED(hr)) { CLASSDATA cd; IDs ids; hr = GetFirst_ClassData(pConn, dObjectId, cd, dwPropertyID); while (SUCCEEDED(hr)) { if (dwPropertyID == cd.iPropertyId && dwRefID == cd.iQfrPos && cd.iArrayPos >= i) { ids.push_back (cd.iArrayPos); } hr = GetNext_ClassData(pConn, cd); if (dObjectId != cd.dObjectId) { cd.Clear(); break; } } hr = WBEM_S_NO_ERROR; for (i = 0; i < ids.size(); i++) hr = DeleteClassData(pConn, dwPropertyID, dObjectId, ids.at(i)); } delete pQfr; } } return hr; } HRESULT CWmiDbSession::CustomGetObject(IWmiDbHandle *pScope, IWbemPath *pPath, LPWSTR lpObjectKey, DWORD dwFlags, DWORD dwRequestedHandleType, IWmiDbHandle **ppResult) {return E_NOTIMPL;} HRESULT CWmiDbSession::CustomGetMapping(CSQLConnection *pConn, IWmiDbHandle *pScope, LPWSTR lpClassName, IWbemClassObject **ppMapping) {return E_NOTIMPL;} HRESULT CWmiDbSession::CustomCreateMapping(CSQLConnection *pConn, LPWSTR lpClassName, IWbemClassObject *pClassObj, IWmiDbHandle *pScope) {return E_NOTIMPL;} HRESULT CWmiDbSession::CustomPutInstance(CSQLConnection *pConn, IWmiDbHandle *pScope, SQL_ID dClassId, DWORD dwFlags, IWbemClassObject **ppObjToPut, LPWSTR lpClassName) {return E_NOTIMPL;} HRESULT CWmiDbSession::CustomFormatSQL(IWmiDbHandle *pScope, IWbemQuery *pQuery, _bstr_t &sSQL, SQL_ID *dClassId, MappedProperties **ppMapping, DWORD *dwNumProps, BOOL *bCount) {return E_NOTIMPL;} HRESULT CWmiDbSession::CustomDelete(CSQLConnection *pConn, IWmiDbHandle *pScope, IWmiDbHandle *pHandle, LPWSTR lpClassName) {return E_NOTIMPL;}