/***************************************************************************/ /* ISAM.C */ /* Copyright (C) 1995-96 SYWARE Inc., All rights reserved */ /***************************************************************************/ // Commenting #define out - causing compiler error - not sure if needed, compiles // okay without it. //#define WINVER 0x0400 #include "precomp.h" #include "wbemidl.h" #include //smart pointer _COM_SMARTPTR_TYPEDEF(IWbemServices, IID_IWbemServices); _COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, IID_IEnumWbemClassObject); //_COM_SMARTPTR_TYPEDEF(IWbemContext, IID_IWbemContext ); _COM_SMARTPTR_TYPEDEF(IWbemLocator, IID_IWbemLocator); _COM_SMARTPTR_TYPEDEF(IWbemClassObject, IID_IWbemClassObject); _COM_SMARTPTR_TYPEDEF(IWbemQualifierSet, IID_IWbemQualifierSet); #include "drdbdr.h" #include "float.h" #include "resource.h" #include //for _bstr_t #include #include "cominit.h" //for Dcom blanket #include //for _beginthreadex #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //Some standard SYNTAX/CIMTYPE qualifier string constants //#define WBEM_WSYNTAX_CHAR L"CHAR" //#define WBEM_WSYNTAX_INT8 L"INT8" #define WBEM_WSYNTAX_UINT8 L"UINT8" #define WBEM_WSYNTAX_SINT8 L"SINT8" //#define WBEM_WSYNTAX_UCHAR L"UCHAR" //#define WBEM_WSYNTAX_BYTE L"BYTE" //#define WBEM_WSYNTAX_INT64 L"INT64" #define WBEM_WSYNTAX_SINT64 L"SINT64" #define WBEM_WSYNTAX_UINT64 L"UINT64" //#define WBEM_WSYNTAX_INTERVAL L"INTERVAL" #define WBEM_WSYNTAX_DATETIME L"DATETIME" //#define WBEM_WSYNTAX_DATE L"DATE" //#define WBEM_WSYNTAX_TIME L"TIME" #define WBEM_WSYNTAX_STRING L"STRING" //#define WBEM_WSYNTAX_DWORD L"DWORD" //#define WBEM_WSYNTAX_ULONG L"ULONG" //#define WBEM_WSYNTAX_UINT L"UINT" #define WBEM_WSYNTAX_SINT32 L"SINT32" #define WBEM_WSYNTAX_UINT32 L"UINT32" //#define WBEM_WSYNTAX_LONG L"LONG" //#define WBEM_WSYNTAX_INT L"INT" //#define WBEM_WSYNTAX_INTEGER L"INTEGER" //#define WBEM_WSYNTAX_INT32 L"INT32" //#define WBEM_WSYNTAX_WCHAR L"WCHAR" //#define WBEM_WSYNTAX_WCHAR_T L"WCHAR_T" //#define WBEM_WSYNTAX_INT16 L"INT16" //#define WBEM_WSYNTAX_SHORT L"SHORT" #define WBEM_WSYNTAX_SINT16 L"SINT16" #define WBEM_WSYNTAX_UINT16 L"UINT16" //#define WBEM_WSYNTAX_USHORT L"USHORT" //#define WBEM_WSYNTAX_WORD L"WORD" //#define WBEM_WSYNTAX_CHAR L"CHAR" #define WBEM_WSYNTAX_STRING_LEN 6 #define WBEM_SYNTAX_STRING "STRING" #define WBEM_VARIANT_VT_I1 1 #define WBEM_VARIANT_VT_UI1 2 #define WBEM_VARIANT_VT_BSTR 3 #define WBEM_VARIANT_VT_I4 4 #define WBEM_VARIANT_VT_UI4 5 #define WBEM_VARIANT_VT_I2 6 #define WBEM_VARIANT_VT_UI2 7 #define WBEM_VARIANT_VT_R4 8 #define WBEM_VARIANT_VT_R8 9 #define WBEM_VARIANT_VT_I8 10 #define WBEM_VARIANT_VT_UI8 11 #define WBEM_VARIANT_VT_BOOL 12 #define WBEM_VARIANT_VT_ARRAY_I1 13 #define WBEM_VARIANT_VT_ARRAY_UI1 14 #define WBEM_VARIANT_VT_ARRAY_BSTR 15 #define WBEM_VARIANT_VT_ARRAY_I4 16 #define WBEM_VARIANT_VT_ARRAY_UI4 17 #define WBEM_VARIANT_VT_ARRAY_I2 18 #define WBEM_VARIANT_VT_ARRAY_UI2 19 #define WBEM_VARIANT_VT_ARRAY_R4 20 #define WBEM_VARIANT_VT_ARRAY_R8 21 #define WBEM_VARIANT_VT_ARRAY_I8 22 #define WBEM_VARIANT_VT_ARRAY_UI8 23 #define WBEM_VARIANT_VT_ARRAY_BOOL 24 #define WBEM_DSDT_UNKNOWN 0 #define WBEM_DSDT_SINT8 1 #define WBEM_DSDT_UINT8 2 #define WBEM_DSDT_SINT64 3 #define WBEM_DSDT_UINT64 4 //#define WBEM_DSDT_INTERVAL 5 #define WBEM_DSDT_TIMESTAMP 6 //#define WBEM_DSDT_DATE 7 //#define WBEM_DSDT_TIME 8 #define WBEM_DSDT_SMALL_STRING 9 #define WBEM_DSDT_STRING 10 #define WBEM_DSDT_UINT32 11 #define WBEM_DSDT_SINT32 12 #define WBEM_DSDT_SINT16 13 #define WBEM_DSDT_UINT16 14 #define WBEM_DSDT_REAL 15 #define WBEM_DSDT_DOUBLE 16 #define WBEM_DSDT_BIT 17 #define WBEM_DSDT_SINT8_ARRAY 18 #define WBEM_DSDT_UINT8_ARRAY 19 #define WBEM_DSDT_UINT32_ARRAY 20 #define WBEM_DSDT_SINT32_ARRAY 21 #define WBEM_DSDT_BOOL_ARRAY 22 #define WBEM_DSDT_SINT16_ARRAY 23 #define WBEM_DSDT_UINT16_ARRAY 24 #define WBEM_DSDT_REAL_ARRAY 25 #define WBEM_DSDT_DOUBLE_ARRAY 26 #define WBEM_DSDT_SINT64_ARRAY 27 #define WBEM_DSDT_UINT64_ARRAY 28 #define WBEM_DSDT_STRING_ARRAY 29 //#define WBEM_DSDT_INTERVAL_ARRAY 30 #define WBEM_DSDT_TIMESTAMP_ARRAY 31 //#define WBEM_DSDT_DATE_ARRAY 32 //#define WBEM_DSDT_TIME_ARRAY 33 #define WBEM_DSDT_SMALL_STRING_ARRAY 34 BSTR gpPrincipal = NULL; BOOL g_DebugTracingSwitchedOn = FALSE; //global variable void __DuhDoSomething(LPCTSTR myStr,...) { if (g_DebugTracingSwitchedOn) { OutputDebugString(myStr); //Write data to file /* FILE* hfile = fopen("wbemdr32.log", "a"); if (hfile) { fwrite(myStr, _mbstrlen(myStr) + 1, _mbstrlen(myStr) + 1, hfile); fclose(hfile); } */ } } //used to create and manage worker thread CWorkerThreadManager glob_myWorkerThread; BOOL IsW2KOrMore(void) { OSVERSIONINFO os; os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if(!GetVersionEx(&os)) return FALSE; // should never happen return ( os.dwPlatformId == VER_PLATFORM_WIN32_NT ) && ( os.dwMajorVersion >= 5 ) ; } HRESULT WbemSetDynamicCloaking(IUnknown* pProxy, DWORD dwAuthnLevel, DWORD dwImpLevel) { ODBCTRACE("\nWBEM ODBC Driver : WbemSetDynamicCloaking\n"); HRESULT hres; if(!IsW2KOrMore()) { // Not NT5 --- don't bother // ======================== ODBCTRACE("\nWBEM ODBC Driver : WbemSetDynamicCloaking : Not NT5 --- don't bother\n"); return WBEM_S_FALSE; } // Try to get IClientSecurity from it // ================================== IClientSecurity* pSec; hres = pProxy->QueryInterface(IID_IClientSecurity, (void**)&pSec); if(FAILED(hres)) { // Not a proxy --- not a problem // ============================= ODBCTRACE("\nWBEM ODBC Driver : WbemSetDynamicCloaking : Not a proxy --- not a problem\n"); return WBEM_S_FALSE; } DWORD dwSize = 1000; char buffer[1001]; buffer[0] = 0; if ( GetUserName(buffer, &dwSize) ) { CString lpMessage; lpMessage.Format("\nUser Account just before SetBlanket is %ld characters long : %s\n", dwSize, buffer); ODBCTRACE(lpMessage); } else { ODBCTRACE("\nGetUserName call failed just before SetBlanket\n"); } hres = pSec->SetBlanket(pProxy, RPC_C_AUTHN_DEFAULT,//0xa,//RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_DEFAULT,//0,//RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CONNECT,//2,//dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE,//3,//dwImpLevel, NULL, EOAC_DYNAMIC_CLOAKING//0x20 ); pSec->Release(); if (SUCCEEDED(hres)) { ODBCTRACE("\nWBEM ODBC Driver : WbemSetDynamicCloaking : SUCCEEDED\n"); } else { ODBCTRACE("\nWBEM ODBC Driver : WbemSetDynamicCloaking : FAILED\n"); } return hres; } HRESULT ISAMSetCloaking1(IUnknown* pProxy, BOOL fIsLocalConnection, BOOL fW2KOrMore, DWORD dwAuthLevel, DWORD dwImpLevel, BSTR authorityBSTR, BSTR userBSTR, BSTR passwdBSTR, COAUTHIDENTITY ** gpAuthIdentity) { HRESULT sc = WBEM_S_FALSE; if ( fIsLocalConnection && fW2KOrMore ) { sc = WbemSetDynamicCloaking(pProxy, dwAuthLevel, dwImpLevel); } else { sc = SetInterfaceSecurityEx(pProxy, authorityBSTR, userBSTR, passwdBSTR, dwAuthLevel, dwImpLevel, EOAC_NONE, gpAuthIdentity, &gpPrincipal ); } return sc; } HRESULT ISAMSetCloaking2(IUnknown* pProxy, BOOL fIsLocalConnection, BOOL fW2KOrMore, DWORD dwAuthLevel, DWORD dwImpLevel, COAUTHIDENTITY * gpAuthIdentity) { HRESULT sc = WBEM_S_FALSE; if ( fIsLocalConnection && fW2KOrMore ) { sc = WbemSetDynamicCloaking(pProxy, dwAuthLevel, dwImpLevel); } else { SetInterfaceSecurityEx(pProxy, gpAuthIdentity, gpPrincipal, dwAuthLevel, dwImpLevel); } return sc; } void ISAMCheckWorkingThread_AllocEnv() { ODBCTRACE("\nISAMCheckWorkingThread_AllocEnv\n"); //Create working thread if necessary if (! glob_myWorkerThread.GetThreadHandle() && ! glob_myWorkerThread.IsValid() ) { ODBCTRACE("\nCreateWorkerThread\n"); glob_myWorkerThread.CreateWorkerThread(); } else { //increament ref count on working thread MyWorkingThreadParams* m_params = new MyWorkingThreadParams(NULL, NULL, 0, NULL); //post message to create this object on working thread CString sMessage; sMessage.Format( "\nCreateWorkerThread : post message to thread %ld\n", glob_myWorkerThread.GetThreadId() ); ODBCTRACE(sMessage); EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); ResetEvent(m_params->m_EventHnd); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); BOOL status = PostThreadMessage(glob_myWorkerThread.GetThreadId(), MYUSRMESS_REFCOUNT_INCR, 0, (LPARAM)m_params); WaitForSingleObject(m_params->m_EventHnd, INFINITE); ODBCTRACE("\nISAMCheckWorkingThread_AllocEnv : exit\n"); delete m_params; } } void ISAMCheckWorkingThread_FreeEnv() { //decrement ref count MyWorkingThreadParams* m_params = new MyWorkingThreadParams(NULL, NULL, 0, NULL); //post message to create this object on working thread EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); HANDLE EventHnd = m_params->m_EventHnd; ResetEvent(EventHnd); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); BOOL status = PostThreadMessage(glob_myWorkerThread.GetThreadId(), MYUSRMESS_REFCOUNT_DECR, 0, (LPARAM)m_params); WaitForSingleObject(EventHnd, INFINITE); delete m_params; //if zero shut down thread if ( ! glob_myWorkerThread.GetRefCount() ) { ISAMCloseWorkerThread1(); //invalidate it glob_myWorkerThread.Invalidate(); } } void ISAMCheckTracingOption() { //Read the registry setting to determine if you //want to enable tracing and set the global variable accordingly //by default logging is switched off g_DebugTracingSwitchedOn = FALSE; HKEY keyHandle = (HKEY)1; long fStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\WBEM", 0, KEY_READ, &keyHandle); if (fStatus == ERROR_SUCCESS) { DWORD dwLogging; DWORD sizebuff = sizeof(DWORD); DWORD typeValue; fStatus = RegQueryValueEx(keyHandle, "ODBC Logging", NULL, &typeValue, (LPBYTE)&dwLogging, &sizebuff); if ( (fStatus == ERROR_SUCCESS) && dwLogging ) { //switch on logging if 'ODBC Logging' is set to a non-zero number g_DebugTracingSwitchedOn = TRUE; } RegCloseKey(keyHandle); } } void INTFUNC ISAMGetSelectStarList(char** lpWQLSelectStarList, //OUT TableColumnInfo* pSelectInfo, //IN LPISAM lpISAM); void Utility_GetLocaleIDFromString(IN char* lpValue, OUT DWORD& _dwLocale) { _bstr_t sFullLocaleStr = lpValue; if(!_wcsnicmp(sFullLocaleStr, L"MS\\", 3)) { DWORD dwLocale = 0; _bstr_t sHexLocaleID = &((wchar_t*)sFullLocaleStr)[3]; swscanf( sHexLocaleID, L"%x", &dwLocale); // Only set if we have a result if(dwLocale) _dwLocale = dwLocale; } } UINT Utility_GetCodePageFromLCID(LCID lcid) { char szLocale[12]; UINT cp; int iNumChars = 0; iNumChars = GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, szLocale, sizeof(szLocale)); if (iNumChars) { szLocale[iNumChars] = '\0'; cp = strtoul(szLocale, NULL, 10); if (cp) return cp; } return GetACP(); } void Utility_SetThreadLocale(IN char* lpValue, ULPSETTHREADLOCALE pProcSetThreadLocale) { // Default to local system Locale DWORD dwLocaleID = GetSystemDefaultLCID(); if(lpValue && strlen(lpValue)) { //Get the locale id from string Utility_GetLocaleIDFromString(lpValue, dwLocaleID); } if (pProcSetThreadLocale) { //Now set the thread locale if((*pProcSetThreadLocale)(dwLocaleID)) { CString myText; myText.Format("\nWBEM ODBC Driver : Set ThreadLocaleID OK to: %d\n",dwLocaleID); ODBCTRACE(myText); } else { (*pProcSetThreadLocale)(GetSystemDefaultLCID()); CString myText; myText.Format("\nWBEM ODBC Driver : Set ThreadLocaleID OK to system default: %d\n",GetSystemDefaultLCID()); ODBCTRACE(myText); } } } int Utility_WideCharToDBCS(IN _bstr_t& _sWCharData, char** rgbValue, SDWORD cbValueMax) { DWORD dwDBCSBuffLen = cbValueMax; UINT cpThread = Utility_GetCodePageFromLCID(GetThreadLocale()); // Tried WC_COMPOSITECHECK, didn't seem to work on Japanese machine int dwDBCSLen = WideCharToMultiByte(cpThread,WC_COMPOSITECHECK, (const wchar_t*)_sWCharData, -1, *rgbValue, cbValueMax, NULL, NULL); //The return length included the NULL terminator //so we need to remove this if (dwDBCSLen) --dwDBCSLen; return dwDBCSLen; } void Utility_DBCSToWideChar(IN const char* _dbcsData, OUT wchar_t** _sOutData, SWORD cbLen) { DWORD dwDbcsLen = cbLen ? (cbLen+1) : (_mbstrlen(_dbcsData)+1); // alloca is much faster (see TN059) *_sOutData = new wchar_t [dwDbcsLen + 1]; *_sOutData[0] = 0; UINT cpThread = Utility_GetCodePageFromLCID(GetThreadLocale()); // tried MB_COMPOSITE didn't work on German machine int dwNumWideChars = MultiByteToWideChar(cpThread, MB_PRECOMPOSED, _dbcsData, cbLen ? dwDbcsLen : -1, *_sOutData,dwDbcsLen); if (!dwNumWideChars) { *_sOutData[0] = 0; } else { if (cbLen) (*_sOutData)[cbLen] = 0; } } class ThreadLocaleIdManager { private: LCID m_lcid; HINSTANCE hKernelApi; ULPSETTHREADLOCALE pProcSetThreadLocale; public : ThreadLocaleIdManager(IN LPISAM lpISAM); ThreadLocaleIdManager(LPUSTR lpLocale); ~ThreadLocaleIdManager(); }; ThreadLocaleIdManager::ThreadLocaleIdManager(IN LPISAM lpISAM) { hKernelApi = NULL; //Save current thread locale id m_lcid = GetThreadLocale(); pProcSetThreadLocale = NULL; if (lpISAM->hKernelApi) { pProcSetThreadLocale = (ULPSETTHREADLOCALE) GetProcAddress(lpISAM->hKernelApi, "SetThreadLocale"); } //Change thread locale id Utility_SetThreadLocale(lpISAM->m_Locale, pProcSetThreadLocale); } ThreadLocaleIdManager::ThreadLocaleIdManager(LPUSTR lpLocale) { hKernelApi = LoadLibrary("KERNEL32.DLL"); m_lcid = GetThreadLocale(); pProcSetThreadLocale = NULL; if (hKernelApi) { pProcSetThreadLocale = (ULPSETTHREADLOCALE) GetProcAddress(hKernelApi, "SetThreadLocale"); } //Change thread locale id Utility_SetThreadLocale((char*)lpLocale, pProcSetThreadLocale); } ThreadLocaleIdManager::~ThreadLocaleIdManager() { //Restore thread locale id on destruction if (pProcSetThreadLocale) { (*pProcSetThreadLocale)(m_lcid); } if (hKernelApi) { BOOL status = FreeLibrary(hKernelApi); if (! status) { DWORD err = GetLastError(); CString message ("\n\n***** FreeLibrary KERNEL32 failed : %ld*****\n\n", err); ODBCTRACE(message); } } } void ISAMStringConcat(char** resultString, char* myStr) { if (myStr) { ULONG len = s_lstrlen(myStr); ULONG oldLen = 0; if (resultString && *resultString) oldLen = s_lstrlen(*resultString); char* buffer = new char [oldLen + len + 1]; buffer[0] = 0; if (oldLen) { sprintf (buffer, "%s%s", *resultString, myStr); } else { s_lstrcpy(buffer, myStr); } //delete old string if (resultString && *resultString) delete (*resultString); //replace with new string *resultString = buffer; } } ImpersonationManager::ImpersonationManager(char* org_szUser, char* org_szPassword, char* org_szAuthority) { ODBCTRACE(_T("\nWBEM ODBC Driver : ImpersonationManager constructor\n")); hToken = NULL; hAdvApi = NULL; // hKernelApi = NULL; pProcLogonUser = NULL; pProcImpersonateLoggedOnUser = NULL; pProcRevertToSelf = NULL; fImpersonatingNow = FALSE; //We need to do a LoadLibrary //as the inpersonation struff is not avaiable on //Windows 95 and Win32s fImpersonate = DoInitialChecks(); if ( CanWeImpersonate() ) { //Extract logon info ExtractLogonInfo(org_szUser, org_szPassword, org_szAuthority); } } void ImpersonationManager::ExtractLogonInfo(char* org_szUser, char* szPassword, char* szAuthority) { //The user name could be the domain and user id //Make a copy of the username szUser[0] = 0; if (org_szUser && strlen(org_szUser)) strncpy(szUser, org_szUser, MAX_USER_NAME_LENGTH); szUser[MAX_USER_NAME_LENGTH] = 0; //Find backslash character char* lpDomain = NULL; char* lpUser = szUser; int ch = '\\'; char* backslashPtr = strchr(szUser, ch); if (backslashPtr) { //Found backslash, therefore username //is domainuserid lpDomain = szUser; lpUser = backslashPtr + 1; *backslashPtr = 0; //NULL the backslash so we get two strings } else { //no domain in user name //so set domain to authority value lpDomain = szAuthority; } //Call LogonUser via pointer to function BOOL status = (*pProcLogonUser)( lpUser, lpDomain, szPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken ); if (!status) { status = (*pProcLogonUser)( lpUser, lpDomain, szPassword, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &hToken ); } if (status) { ODBCTRACE(_T("\nWBEM ODBC Driver : LogonUser call SUCCEEDED, now impersonating user ")); ODBCTRACE(_T(lpUser)); if (lpDomain && strlen(lpDomain)) { ODBCTRACE(_T(" on domain ")); ODBCTRACE(_T(lpDomain)); } ODBCTRACE(_T("\n")); Impersonate(); } else { ODBCTRACE(_T("\nWBEM ODBC Driver : LogonUser call failed, not doing impersonation for user ")); ODBCTRACE(_T(lpUser)); if (lpDomain && strlen(lpDomain)) { ODBCTRACE(_T(" on domain ")); ODBCTRACE(_T(lpDomain)); } ODBCTRACE(_T("\n")); CString lastErr; lastErr.Format ("Last Error = %ld \n", GetLastError() ); ODBCTRACE (lastErr); hToken = NULL; fImpersonate = FALSE; } } BOOL ImpersonationManager::DoInitialChecks() { BOOL fError = FALSE; //Retieve pointer to functions you want to call // (only on Windows NT) hAdvApi = LoadLibrary("ADVAPI32.DLL"); // hKernelApi = LoadLibrary("KERNEL32.DLL"); // if (hAdvApi && hKernelApi) if (hAdvApi) { //LogonUser pProcLogonUser = (ULPLOGONUSER) GetProcAddress(hAdvApi, "LogonUserA"); //ImpersonateLoggedOnUser pProcImpersonateLoggedOnUser = (ULPIMPERSONLOGGEDONUSER) GetProcAddress(hAdvApi, "ImpersonateLoggedOnUser"); //RevertToSelf pProcRevertToSelf = (ULPREVERTTOSELF) GetProcAddress(hAdvApi, "RevertToSelf"); //Check that you have valid pointers to all of these functions if ( (!pProcLogonUser) || (!pProcImpersonateLoggedOnUser) || (!pProcRevertToSelf) ) { fError = TRUE; } } else { fError = TRUE; hAdvApi = NULL; } if (fError) { //Can't load libaries so fail ODBCTRACE(_T("\nWBEM ODBC Driver : Impersonation libraries/function failier !!!\n")); if (hAdvApi) { FreeLibrary(hAdvApi); hAdvApi = NULL; } // if (hKernelApi) // { // FreeLibrary(hKernelApi); // hKernelApi = NULL; // } } else { //success ODBCTRACE(_T("\nWBEM ODBC Driver : We can do impersonation !!!\n")); return TRUE; } //Default is failure to impersonate return FALSE; } ImpersonationManager::~ImpersonationManager() { ODBCTRACE(_T("\nWBEM ODBC Driver : ImpersonationManager DESTRUCTOR\n")); //If you are doing a SQLDisconnect this class will //be deleted by something like ISAMClose //Revert back to original user at this point //as it won't be done in destructor of MyImpersonator RevertToYourself(); if (hAdvApi) { ODBCTRACE(_T("\nWBEM ODBC Driver : FreeLibrary(hAdvApi)\n")); FreeLibrary(hAdvApi); } // if (hKernelApi) // { // FreeLibrary(hKernelApi); // } if (hToken) { ODBCTRACE(_T("\nWBEM ODBC Driver : CloseHandle(hToken)\n")); CloseHandle(hToken); } } void ImpersonationManager::Impersonate(char* str) { if (fImpersonatingNow) { ODBCTRACE("\nWBEM ODBC Driver : ImpersonationManager::Impersonate - already impersonating\n"); } //Call ImpersonateLoggedOnUser via pointer to function if ( CanWeImpersonate() && hToken && !fImpersonatingNow ) { BOOL status = (*pProcImpersonateLoggedOnUser)( hToken ); CString myText(_T("\nWBEM ODBC Driver : ")); //Name of function if (str) { myText += str; myText += _T(" : "); } myText += _T("Impersonating the logged on user "); //User account you are impersonating if (szUser) { myText += _T("["); myText += _T(szUser); myText += _T("]"); } if (status) { myText += _T("\n"); } else { myText += _T(" FAILED\n"); } ODBCTRACE(myText); if (status) fImpersonatingNow = TRUE; } } void ImpersonationManager::RevertToYourself(char* str) { //If impersonation is taking place //revert to original user //Call RevertToSelf via pointer to function if ( CanWeImpersonate() && fImpersonatingNow ) { (*pProcRevertToSelf)(); fImpersonatingNow = FALSE; CString myText(_T("\nWBEM ODBC Driver : ")); if (str) { myText += _T(str); myText += _T(" : "); } myText += _T("Reverting To Self\n"); ODBCTRACE(myText); } } /***********************************************/ MyImpersonator::MyImpersonator(LPDBC myHandle, char* str) { hdl = myHandle; hstmt = NULL; lpISAM = NULL; lpImpersonator = NULL; displayStr = str; if (hdl->lpISAM && hdl->lpISAM->Impersonate) { hdl->lpISAM->Impersonate->Impersonate(displayStr); } } MyImpersonator::MyImpersonator(LPSTMT myHandle, char* str) { hdl = NULL; lpISAM = NULL; hstmt = myHandle; displayStr = str; lpImpersonator = NULL; if (hstmt->lpdbc && hstmt->lpdbc->lpISAM && hstmt->lpdbc->lpISAM->Impersonate) { hstmt->lpdbc->lpISAM->Impersonate->Impersonate(displayStr); } } MyImpersonator::MyImpersonator(LPISAM myHandle, char* str) { hdl = NULL; hstmt = NULL; lpISAM = myHandle; displayStr = str; lpImpersonator = NULL; if ( !lpISAM ) ODBCTRACE("\nWBEM ODBC Driver : lpISAM is NULL\n"); if (lpISAM && lpISAM->Impersonate) { BOOL copyOfFlag = lpISAM->Impersonate->fImpersonatingNow; lpISAM->Impersonate->fImpersonatingNow = FALSE; lpISAM->Impersonate->Impersonate(displayStr); lpISAM->Impersonate->fImpersonatingNow = copyOfFlag; } else { ODBCTRACE("\nWBEM ODBC Driver : lpISAM->Impersonate is NULL\n"); } } MyImpersonator::MyImpersonator(char* szUser, char* szPassword, char* szAuthority, char* str) { hdl = NULL; hstmt = NULL; lpISAM = NULL; displayStr = str; lpImpersonator = new ImpersonationManager(szUser, szPassword, szAuthority); lpImpersonator->Impersonate(displayStr); } MyImpersonator::~MyImpersonator() { if (hdl) { if (hdl->lpISAM && hdl->lpISAM->Impersonate) { hdl->lpISAM->Impersonate->RevertToYourself(displayStr); } } else if (hstmt) { if (hstmt->lpdbc && hstmt->lpdbc->lpISAM && hstmt->lpdbc->lpISAM->Impersonate) { hstmt->lpdbc->lpISAM->Impersonate->RevertToYourself(displayStr); } } else if (lpISAM) { if (lpISAM->Impersonate) { BOOL copyOfFlag = lpISAM->Impersonate->fImpersonatingNow; lpISAM->Impersonate->fImpersonatingNow = TRUE; lpISAM->Impersonate->RevertToYourself(displayStr); lpISAM->Impersonate->fImpersonatingNow = copyOfFlag; } } else if (lpImpersonator) { //deleting will call RevertToYourself delete lpImpersonator; } } CBString::CBString(int nSize) { m_pString = SysAllocStringLen(NULL, nSize); m_temp = NULL; } CBString::CBString(WCHAR* pwszString, BOOL fInterpretAsBlank) { m_temp = NULL; m_pString = NULL; if (pwszString) { if ( wcslen(pwszString) ) { m_pString = SysAllocString(pwszString); } else { //OK, we have a string of zero length //check if we interpret this as blank or NULL if (fInterpretAsBlank) { m_temp = new wchar_t[1]; m_temp[0] = 0; m_pString = SysAllocString(m_temp); } } } } CBString::~CBString() { delete m_temp; if(m_pString) { SysFreeString(m_pString); m_pString = NULL; } } /***************************************************************************/ /* Formats string parameter for output in square braces */ SWORD INTFUNC ISAMFormatCharParm (char* theValue, BOOL &fOutOfBufferSpace, char* rgbValue, SDWORD cbValueMax, SDWORD FAR* pcbValue, BOOL fIsBinaryOutput, SDWORD fInt64Check = 0, BOOL fAllElements = TRUE) { //Now we must add in string value in the format [string] //However, if the string contains either [ or ] we must double //this character in the string sequence fOutOfBufferSpace = FALSE; //First store a reference to length of current string //in case we run out of buffer space when adding this string SDWORD pcbOldValue = (*pcbValue); //Do we need to show surrounding braces //Not for binary output or if we only want to //show one instance BOOL fSurroundingBraces = TRUE; if (fIsBinaryOutput) fSurroundingBraces = FALSE; if (!fAllElements) fSurroundingBraces = FALSE; //Add leading [ character (not for binary) if (fSurroundingBraces) { if ((1 + (*pcbValue)) <= cbValueMax) { rgbValue[(*pcbValue)] = '['; (*pcbValue) += 1; } else { fOutOfBufferSpace = TRUE; } } //Add each character in string checking for [ or ] (not for binary) ULONG cLengthOfElementString = 0; if (theValue) cLengthOfElementString = lstrlen(theValue); if (!fOutOfBufferSpace && cLengthOfElementString) { //Copy each character ULONG cIndex = 0; while ( (!fOutOfBufferSpace) && theValue[cIndex] ) { //How much buffer space do we have left SDWORD cbSpaceLeft = cbValueMax - (*pcbValue); //???We need to add the character(s) and a NULL terminator // if ( (fSurroundingBraces) && ((theValue[cIndex] == '[') || (theValue[cIndex] == ']')) // && (cbSpaceLeft >= 2) ) if ( (fSurroundingBraces) && ((theValue[cIndex] == '[') || (theValue[cIndex] == ']')) ) { // if (cbSpaceLeft >= 3) if (cbSpaceLeft >= 2) { //Add the character in TWICE rgbValue[(*pcbValue)] = theValue[cIndex]; rgbValue[(*pcbValue) + 1] = theValue[cIndex]; //rgbValue[(*pcbValue) + 2] = 0; (*pcbValue) += 2; } else { fOutOfBufferSpace = TRUE; } } else { // if (cbSpaceLeft >= 2) if (cbSpaceLeft) { //Add the character in ONCE rgbValue[(*pcbValue)] = theValue[cIndex]; //rgbValue[(*pcbValue) + 1] = 0; (*pcbValue) += 1; } else { fOutOfBufferSpace = TRUE; } } //Extra check if this is a 64 bit integer if (fInt64Check == WBEM_DSDT_SINT64) { switch (theValue[cIndex]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '+': case '-': //OK break; default: { *pcbValue = 0; return ERR_INVALID_INTEGER; } break; } } if (fInt64Check == WBEM_DSDT_UINT64) { switch (theValue[cIndex]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': //OK break; default: { *pcbValue = 0; return ERR_INVALID_INTEGER; } break; } } cIndex++; } } //Add trailing ] character (not for binary) if (fSurroundingBraces) { if ((!fOutOfBufferSpace) && ((1 + (*pcbValue)) <= cbValueMax)) { rgbValue[(*pcbValue)] = ']'; (*pcbValue) += 1; } else { fOutOfBufferSpace = TRUE; } } //If you run out of buffer space indicate to truncate if (fOutOfBufferSpace) { (*pcbValue) = pcbOldValue; return ISAM_TRUNCATION; } return NO_ISAM_ERR; } /***************************************************************************/ /* This static function attempts to extract the precision from a property SYNTAX/CIMTYPE string */ /* The SYNTAX/CIMTYPE string will be in the format: */ /* name(precision) [ e.g. STRING(10) ] */ /* The value of 'name' is input as the 1st parameter to this function */ /* The 2nd parameter to this function is the whole SYNTAX/CIMTYPE string */ /* The return value is the precision extracted */ /* If an error occurs 0 is returned */ static LONG GetPrecisionFromSyntaxStr(char* lpHeaderStr, char* lpString) { //Check for a valid input strings if (!lpHeaderStr || !lpString) return 0; //Check lengths of strings LONG cHeaderLen = lstrlen(lpHeaderStr); LONG cStrLen = lstrlen(lpString); if ( !cHeaderLen || !cStrLen || (cStrLen < cHeaderLen) ) return 0; //Set position to expected '(' char* pSearchPos = lpString + cHeaderLen; char* pNumStart = NULL; //skip leading white space while (*pSearchPos && (*pSearchPos == ' ')) { pSearchPos += 1; } if (*pSearchPos != '(') { return 0; } else { //OK, matched the first '(', now continue searching //until you reach the end of the string or the ')' pSearchPos += 1; pNumStart = pSearchPos; while ( *pSearchPos != ')' ) { //Check if we have reached end of string before //finding the ')'. If so return 0 if (*pSearchPos == 0) return 0; else pSearchPos += 1; } *pSearchPos = 0; } return atoi (pNumStart); } /***************************************************************************/ BOOL INTFUNC ISAMGetWbemVariantType(LONG pType, SWORD& wTheVariantType) { BOOL fValidType = TRUE; switch ( pType ) { case CIM_SINT8: //was VT_I1: { wTheVariantType = WBEM_VARIANT_VT_I1; } break; case CIM_UINT8: //was VT_UI1: { wTheVariantType = WBEM_VARIANT_VT_UI1; } break; case CIM_SINT16: //was VT_I2: { wTheVariantType = WBEM_VARIANT_VT_I2; } break; case CIM_UINT16: //was VT_UI2: { wTheVariantType = WBEM_VARIANT_VT_UI2; } break; case CIM_REAL32: //was VT_R4: { wTheVariantType = WBEM_VARIANT_VT_R4; } break; case CIM_REAL64: //was VT_R8: { wTheVariantType = WBEM_VARIANT_VT_R8; } break; case CIM_BOOLEAN: //was VT_BOOL: { wTheVariantType = WBEM_VARIANT_VT_BOOL; } break; case CIM_SINT32: //was VT_I4: { wTheVariantType = WBEM_VARIANT_VT_I4; } break; case CIM_UINT32: //was VT_UI4: { wTheVariantType = WBEM_VARIANT_VT_UI4; } break; case CIM_SINT64: //was VT_I8: { wTheVariantType = WBEM_VARIANT_VT_I8; } break; case CIM_UINT64: //was VT_UI8: { wTheVariantType = WBEM_VARIANT_VT_UI8; } break; case CIM_REFERENCE: case CIM_STRING: //was VT_BSTR case CIM_DATETIME: { wTheVariantType = WBEM_VARIANT_VT_BSTR; } break; default: { //Check if it is a CIM_FLAG_ARRAY type if (pType == (CIM_FLAG_ARRAY | CIM_SINT8)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_I1; } else if (pType == (CIM_FLAG_ARRAY | CIM_UINT8)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_UI1; } else if (pType == (CIM_FLAG_ARRAY | CIM_SINT32)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_I4; } else if (pType == (CIM_FLAG_ARRAY | CIM_UINT32)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_UI4; } else if (pType == (CIM_FLAG_ARRAY | CIM_SINT16)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_I2; } else if (pType == (CIM_FLAG_ARRAY | CIM_UINT16)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_UI2; } else if (pType == (CIM_FLAG_ARRAY | CIM_SINT64)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_I8; } else if (pType == (CIM_FLAG_ARRAY | CIM_UINT64)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_UI8; } else if (pType == (CIM_FLAG_ARRAY | CIM_REAL32)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_R4; } else if (pType == (CIM_FLAG_ARRAY | CIM_REAL64)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_R8; } else if (pType == (CIM_FLAG_ARRAY | CIM_BOOLEAN)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_BOOL; } else if (pType == (CIM_FLAG_ARRAY | CIM_STRING)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_BSTR; } else if (pType == (CIM_FLAG_ARRAY | CIM_REFERENCE)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_BSTR; } else if (pType == (CIM_FLAG_ARRAY | CIM_DATETIME)) { wTheVariantType = WBEM_VARIANT_VT_ARRAY_BSTR; } else { //unknown type fValidType = FALSE; } } break; } return fValidType; } /***************************************************************************/ BOOL INTFUNC ISAMGetDataSourceDependantTypeInfo(SWORD wVariantType, BSTR syntaxStr, SDWORD maxLenVal, SWORD& wDSDT, SWORD& fSqlType, UDWORD& cbPrecision) { //Initialize BOOL fValidType = TRUE; wDSDT = WBEM_DSDT_UNKNOWN; switch (wVariantType) { case WBEM_VARIANT_VT_I1: { fSqlType = SQL_TINYINT; cbPrecision = UTINYINT_PRECISION; wDSDT = WBEM_DSDT_SINT8; } break; case WBEM_VARIANT_VT_UI1: { fSqlType = SQL_TINYINT; cbPrecision = UTINYINT_PRECISION; wDSDT = WBEM_DSDT_UINT8; } break; case WBEM_VARIANT_VT_I2: { wDSDT = WBEM_DSDT_SINT16; fSqlType = SQL_SMALLINT; cbPrecision = SMALLINT_PRECISION; } break; case WBEM_VARIANT_VT_UI2: { wDSDT = WBEM_DSDT_UINT16; fSqlType = SQL_SMALLINT; cbPrecision = SMALLINT_PRECISION; } break; case WBEM_VARIANT_VT_I4: { wDSDT = WBEM_DSDT_SINT32; fSqlType = SQL_INTEGER; cbPrecision = ULONG_PRECISION; } break; case WBEM_VARIANT_VT_UI4: { wDSDT = WBEM_DSDT_UINT32; fSqlType = SQL_INTEGER; cbPrecision = ULONG_PRECISION; } break; case WBEM_VARIANT_VT_I8: { fSqlType = SQL_BIGINT; cbPrecision = 19; wDSDT = WBEM_DSDT_SINT64; } break; case WBEM_VARIANT_VT_UI8: { fSqlType = SQL_BIGINT; cbPrecision = 20; wDSDT = WBEM_DSDT_UINT64; } break; case WBEM_VARIANT_VT_BSTR: { if (syntaxStr) { if (_wcsnicmp(WBEM_WSYNTAX_STRING, syntaxStr, WBEM_WSYNTAX_STRING_LEN) ==0) { LONG cbThePrecision = 254; //The precision of a string could optionally be stored in //the MAXLEN qualifier, let us try and get it if (maxLenVal > 0) { cbThePrecision = maxLenVal; //Double check for *bad* MAXLEN values if (cbThePrecision == 0) { cbThePrecision = 254; } } if (cbThePrecision > 254) { fSqlType = SQL_LONGVARCHAR; //Got precision, so use it cbPrecision = (cbThePrecision > (long)ISAM_MAX_LONGVARCHAR) ? ISAM_MAX_LONGVARCHAR : cbThePrecision; wDSDT = WBEM_DSDT_STRING; } else { fSqlType = SQL_VARCHAR; if (cbThePrecision) { //Got precision, so use it cbPrecision = cbThePrecision; } else { //Could not get precision so use default cbPrecision = 254; } wDSDT = WBEM_DSDT_SMALL_STRING; } } else if(_wcsicmp(WBEM_WSYNTAX_DATETIME, syntaxStr) == 0) { fSqlType = SQL_TIMESTAMP; #if TIMESTAMP_SCALE cbPrecision = 20 + TIMESTAMP_SCALE; #else cbPrecision = 19; #endif wDSDT = WBEM_DSDT_TIMESTAMP; } else { //No match, default to SMALL_STRING fSqlType = SQL_VARCHAR; cbPrecision = 254; wDSDT = WBEM_DSDT_SMALL_STRING; } } else { //No Syntax string, default to SMALL_STRING fSqlType = SQL_VARCHAR; cbPrecision = 254; wDSDT = WBEM_DSDT_SMALL_STRING; } } break; case WBEM_VARIANT_VT_R4: { fSqlType = SQL_DOUBLE; cbPrecision = REAL_PRECISION; wDSDT = WBEM_DSDT_REAL; } break; case WBEM_VARIANT_VT_R8: { fSqlType = SQL_DOUBLE; cbPrecision = DOUBLE_PRECISION; wDSDT = WBEM_DSDT_DOUBLE; //WBEM_DSDT_REAL; } break; case WBEM_VARIANT_VT_BOOL: { fSqlType = SQL_BIT; cbPrecision = BOOL_PRECISION; wDSDT = WBEM_DSDT_BIT; //WBEM_DSDT_REAL; } break; case WBEM_VARIANT_VT_ARRAY_I1: { fSqlType = SQL_TINYINT;//SQL_LONGVARBINARY; cbPrecision = 3;//ISAM_MAX_LONGVARCHAR; wDSDT = WBEM_DSDT_SINT8_ARRAY; } break; case WBEM_VARIANT_VT_ARRAY_UI1: { fSqlType = SQL_TINYINT; //SQL_LONGVARBINARY; cbPrecision = 3; //ISAM_MAX_LONGVARCHAR; wDSDT = WBEM_DSDT_UINT8_ARRAY; } break; case WBEM_VARIANT_VT_ARRAY_I2: { fSqlType = SQL_SMALLINT; //SQL_LONGVARBINARY; cbPrecision = 5; //ISAM_MAX_LONGVARCHAR; wDSDT = WBEM_DSDT_SINT16_ARRAY; } break; case WBEM_VARIANT_VT_ARRAY_UI2: { fSqlType = SQL_SMALLINT; //SQL_LONGVARBINARY; cbPrecision = SMALLINT_PRECISION; //ISAM_MAX_LONGVARCHAR; wDSDT = WBEM_DSDT_UINT16_ARRAY; } break; case WBEM_VARIANT_VT_ARRAY_I4: { fSqlType = SQL_INTEGER; //SQL_LONGVARBINARY; cbPrecision = 10; //ISAM_MAX_LONGVARCHAR; wDSDT = WBEM_DSDT_SINT32_ARRAY; } break; case WBEM_VARIANT_VT_ARRAY_UI4: { fSqlType = SQL_INTEGER; //SQL_LONGVARBINARY; cbPrecision = 10; //ISAM_MAX_LONGVARCHAR; wDSDT = WBEM_DSDT_UINT32_ARRAY; } break; case WBEM_VARIANT_VT_ARRAY_I8: { fSqlType = SQL_BIGINT; //SQL_LONGVARBINARY; cbPrecision = 19; //ISAM_MAX_LONGVARCHAR; wDSDT = WBEM_DSDT_SINT64_ARRAY; } break; case WBEM_VARIANT_VT_ARRAY_UI8: { fSqlType = SQL_BIGINT; //SQL_LONGVARBINARY; cbPrecision = 20; //ISAM_MAX_LONGVARCHAR; wDSDT = WBEM_DSDT_UINT64_ARRAY; } break; case WBEM_VARIANT_VT_ARRAY_BOOL: { fSqlType = SQL_BIT; //SQL_LONGVARBINARY; cbPrecision = BOOL_PRECISION; //ISAM_MAX_LONGVARCHAR; wDSDT = WBEM_DSDT_BOOL_ARRAY; } break; case WBEM_VARIANT_VT_ARRAY_R4: { fSqlType = SQL_DOUBLE; //SQL_LONGVARBINARY; cbPrecision = REAL_PRECISION; //ISAM_MAX_LONGVARCHAR; wDSDT = WBEM_DSDT_REAL_ARRAY; } break; case WBEM_VARIANT_VT_ARRAY_R8: { fSqlType = SQL_DOUBLE; //SQL_LONGVARBINARY; cbPrecision = 15; //ISAM_MAX_LONGVARCHAR; wDSDT = WBEM_DSDT_DOUBLE_ARRAY; } break; case WBEM_VARIANT_VT_ARRAY_BSTR: { fSqlType = SQL_VARCHAR; //SQL_LONGVARCHAR; //SQL_LONGVARBINARY; cbPrecision = 254; //ISAM_MAX_LONGVARCHAR; if (syntaxStr) { if (_wcsnicmp(WBEM_WSYNTAX_STRING, syntaxStr, WBEM_WSYNTAX_STRING_LEN) ==0) { LONG cbThePrecision = 254; //The precision of a string could optionally be stored in //the MAXLEN qualifier, let us try and get it if (maxLenVal > 0) { cbThePrecision = maxLenVal; //Double check for *bad* MAXLEN values if (cbThePrecision == 0) { cbThePrecision = 254; } } if (cbThePrecision > 254) { fSqlType = SQL_LONGVARCHAR; //Got precision, so use it cbPrecision = (cbThePrecision > (long)ISAM_MAX_LONGVARCHAR) ? ISAM_MAX_LONGVARCHAR : cbThePrecision; wDSDT = WBEM_DSDT_STRING_ARRAY; } else { fSqlType = SQL_VARCHAR; if (cbThePrecision) { //Got precision, so use it cbPrecision = cbThePrecision; } else { //Could not get precision so use default cbPrecision = 254; } wDSDT = WBEM_DSDT_SMALL_STRING_ARRAY; } } else if (_wcsicmp(WBEM_WSYNTAX_DATETIME, syntaxStr) == 0) { wDSDT = WBEM_DSDT_TIMESTAMP_ARRAY; fSqlType = SQL_TIMESTAMP; #if TIMESTAMP_SCALE cbPrecision = 20 + TIMESTAMP_SCALE; #else cbPrecision = 19; #endif } else { //No match, default to SMALL STRING array wDSDT = WBEM_DSDT_SMALL_STRING_ARRAY; } } else { //No Syntax String, default to SMALL STRING array wDSDT = WBEM_DSDT_SMALL_STRING_ARRAY; } } break; default: fValidType = FALSE; break; } //Return indication if this is a valid type return fValidType; } /***************************************************************************/ /* Returns Data-Source Dependent type name in pre-allocated buffer */ void INTFUNC ISAMGetDataSourceDependantTypeStr(SWORD wDSDT, char* lpString) { lpString[0] = 0; switch (wDSDT) { case WBEM_DSDT_SINT8: lstrcpy(lpString, "SINT8"); break; case WBEM_DSDT_UINT8: lstrcpy(lpString, "UINT8"); break; case WBEM_DSDT_SINT64: lstrcpy(lpString, "SINT64"); break; case WBEM_DSDT_UINT64: lstrcpy(lpString, "UINT64"); break; // case WBEM_DSDT_INTERVAL: // lstrcpy(lpString, "INTERVAL"); // break; case WBEM_DSDT_TIMESTAMP: lstrcpy(lpString, "TIMESTAMP"); break; // case WBEM_DSDT_DATE: // lstrcpy(lpString, "DATE"); // break; // case WBEM_DSDT_TIME: // lstrcpy(lpString, "TIME"); // break; case WBEM_DSDT_SMALL_STRING: lstrcpy(lpString, "SMALL_STRING"); break; case WBEM_DSDT_STRING: lstrcpy(lpString, "STRING"); break; case WBEM_DSDT_UINT32: lstrcpy(lpString, "UINT32"); break; case WBEM_DSDT_SINT32: lstrcpy(lpString, "SINT32"); break; case WBEM_DSDT_SINT16: lstrcpy(lpString, "SINT16"); break; case WBEM_DSDT_UINT16: lstrcpy(lpString, "UINT16"); break; case WBEM_DSDT_REAL: lstrcpy(lpString, "REAL"); break; case WBEM_DSDT_DOUBLE: lstrcpy(lpString, "DOUBLE"); break; case WBEM_DSDT_BIT: lstrcpy(lpString, "BIT"); break; case WBEM_DSDT_SINT8_ARRAY: lstrcpy(lpString, "SINT8_ARRAY"); break; case WBEM_DSDT_UINT8_ARRAY: lstrcpy(lpString, "UINT8_ARRAY"); break; case WBEM_DSDT_UINT32_ARRAY: lstrcpy(lpString, "UINT32_ARRAY"); break; case WBEM_DSDT_SINT32_ARRAY: lstrcpy(lpString, "SINT32_ARRAY"); break; case WBEM_DSDT_BOOL_ARRAY: lstrcpy(lpString, "BOOL_ARRAY"); break; case WBEM_DSDT_SINT16_ARRAY: lstrcpy(lpString, "SINT16_ARRAY"); break; case WBEM_DSDT_UINT16_ARRAY: lstrcpy(lpString, "UINT16_ARRAY"); break; case WBEM_DSDT_REAL_ARRAY: lstrcpy(lpString, "REAL_ARRAY"); break; case WBEM_DSDT_DOUBLE_ARRAY: lstrcpy(lpString, "DOUBLE_ARRAY"); break; case WBEM_DSDT_SINT64_ARRAY: lstrcpy(lpString, "SINT64_ARRAY"); break; case WBEM_DSDT_UINT64_ARRAY: lstrcpy(lpString, "UINT64_ARRAY"); break; case WBEM_DSDT_STRING_ARRAY: lstrcpy(lpString, "STRING_ARRAY"); break; case WBEM_DSDT_SMALL_STRING_ARRAY: lstrcpy(lpString, "SMALL_STRING_ARRAY"); break; // case WBEM_DSDT_INTERVAL_ARRAY: // lstrcpy(lpString, "INTERVAL_ARRAY"); // break; case WBEM_DSDT_TIMESTAMP_ARRAY: lstrcpy(lpString, "TIMESTAMP_ARRAY"); break; // case WBEM_DSDT_DATE_ARRAY: // lstrcpy(lpString, "DATE_ARRAY"); // break; // case WBEM_DSDT_TIME_ARRAY: // lstrcpy(lpString, "TIME_ARRAY"); // break; default: break; } } /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ // // Methods for ClassColumnInfo // /***************************************************************************/ /* ClassColumnInfo constructor */ /* */ /* Parameter pType is the Variant type of the property */ // /* Parameter pSYNTAX contains NULL or the SYNTAX string for the property */ /* Parameter fGotSyntax indicates if a SYNTAX string is present */ /* This class is only used internaly by ClassColumnInfoBase and provides */ /* extracts property attribute values, like type, precision, scale */ ClassColumnInfo :: ClassColumnInfo(LONG pType, VARIANT* pSYNTAX, SDWORD maxLenVal, BOOL fGotSyntax, BOOL fIsLazy) { //Initialize VariantInit(&aVariantSYNTAX); szTypeName[0] = 0; fValidType = TRUE; varType = pType; SWORD wDSDT = WBEM_DSDT_UNKNOWN; SWORD wTheVariantType = 0; ibScale = 0; fIsLazyProperty = fIsLazy; //Make a copy of input variants if (fGotSyntax) VariantCopy(&aVariantSYNTAX, pSYNTAX); //Now work out info // Get the column Type, Precision, Scale etc... //You may need to get info from both column value //and SYNTAX attributes in order to map column type to SQL_* type //You may be able to directly map variant type to SQL_* type //however, for some variant types there may be multiple mappings //and so the SYNTAX attribute needs to be fetched in order to //complete the mapping to SQL_* type. fValidType = ISAMGetWbemVariantType(pType, wTheVariantType); if (fValidType) { fValidType = ISAMGetDataSourceDependantTypeInfo (wTheVariantType, (fGotSyntax && aVariantSYNTAX.bstrVal) ? aVariantSYNTAX.bstrVal : NULL, maxLenVal, wDSDT, fSqlType, cbPrecision); if (fValidType) ISAMGetDataSourceDependantTypeStr(wDSDT, (char*)szTypeName); } } /***************************************************************************/ /* Destructor */ ClassColumnInfo :: ~ClassColumnInfo() { //Tidy up VariantClear(&aVariantSYNTAX); } /***************************************************************************/ // // Methods of Class ClassColumnInfoBase // /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ /* ClassColumnInfoBase Constructor */ /* */ /* This class is used as a repository */ /* to extract information about a */ /* property */ ClassColumnInfoBase :: ClassColumnInfoBase(LPISAMTABLEDEF pOrgTableDef, BOOL fIs__Gen) { //Initialize isValid = TRUE; pTableDef = pOrgTableDef; pColumnInformation = NULL; iColumnNumber = 0; fIs__Generic = fIs__Gen; cSystemProperties = 0; embedded = NULL; embeddedSize = 0; //We need to get column information for a column //The information we need is stored in a VALUE variant and the property attribute "SYNTAX" //To get the property attribute "SYNTAX" variant we need the property/column name //Get the column/property name //We do this by getting the list of all property names in a SAFEARRAY //create SAFEARRAY to store BSTR's rgSafeArray = NULL; //Check for pass-through SQL if ( ! (pTableDef->pSingleTable) ) { isValid = FALSE; return; } //Get the names of all the properties/columns SCODE scT = pTableDef->pSingleTable->GetNames ( NULL, 0, NULL, &rgSafeArray ); if (FAILED(scT)) { rgSafeArray = NULL; isValid = FALSE; } else { SafeArrayLock(rgSafeArray); } //Work out number of properties/columns SafeArrayGetLBound(rgSafeArray, 1, &iLBound ); SafeArrayGetUBound(rgSafeArray, 1, &iUBound ); cColumnDefs = (UWORD) (iUBound - iLBound + 1); if (fIs__Generic) { //This class is the prototype class for //a passthrough SQL result set //calculate additional embedded proprties Get__GenericProfile(); } } /***************************************************************************/ /* Destructor */ ClassColumnInfoBase :: ~ClassColumnInfoBase() { //Tidy Up if (rgSafeArray) { SafeArrayUnlock(rgSafeArray); SafeArrayDestroy(rgSafeArray); } if (pColumnInformation) delete pColumnInformation; //SAI ADDED if (cSystemProperties) { if (embedded) { for (UWORD i = 0; i < embeddedSize; i++) { if (embedded[i]) { delete embedded[i]; embedded[i] = NULL; } } delete embedded; embedded = NULL; } } } /***************************************************************************/ /* Sets up extra column information for the selected */ /* column if required */ BOOL ClassColumnInfoBase :: Setup(LONG iColumnNum) { //Sets up extra column information of specified column if ( (!pColumnInformation) || (iColumnNumber != iColumnNum) ) { //Wrong column info, delete old column info //and create for new column if (pColumnInformation) { delete pColumnInformation; pColumnInformation = NULL; } //Setup column info if ( FAILED(GetColumnInfo(iColumnNum)) ) { return FALSE; } else { //Check the newly created column information if (! pColumnInformation->IsValidInfo() ) return FALSE; iColumnNumber = iColumnNum; } } return TRUE; } /***************************************************************************/ BOOL ClassColumnInfoBase :: GetVariantType(LONG iColumnNum, LONG &lVariant) { if ( !Setup(iColumnNum) ) return FALSE; lVariant = pColumnInformation->GetVariantType(); return TRUE; } /***************************************************************************/ BOOL ClassColumnInfoBase :: GetSQLType(LONG iColumnNum, SWORD &wSQLType) { if ( !Setup(iColumnNum) ) return FALSE; wSQLType = pColumnInformation->GetSQLType(); return TRUE; } /***************************************************************************/ BOOL ClassColumnInfoBase :: GetTypeName(LONG iColumnNum, UCHAR* &pbTypeName) { if ( !Setup(iColumnNum) ) return FALSE; pbTypeName = pColumnInformation->GetTypeName(); return TRUE; } /***************************************************************************/ BOOL ClassColumnInfoBase :: GetPrecision(LONG iColumnNum, UDWORD &uwPrecision) { if ( !Setup(iColumnNum) ) return FALSE; uwPrecision = pColumnInformation->GetPrecision(); return TRUE; } /***************************************************************************/ BOOL ClassColumnInfoBase :: GetScale(LONG iColumnNum, SWORD &wScale) { if ( !Setup(iColumnNum) ) return FALSE; wScale = pColumnInformation->GetScale(); return TRUE; } /***************************************************************************/ BOOL ClassColumnInfoBase :: IsNullable(LONG iColumnNum, SWORD &wNullable) { if ( !Setup(iColumnNum) ) return FALSE; wNullable = pColumnInformation->IsNullable(); return TRUE; } /***************************************************************************/ BOOL ClassColumnInfoBase :: IsLazy(LONG iColumnNum, BOOL &fLazy) { if ( !Setup(iColumnNum) ) return FALSE; fLazy = pColumnInformation->IsLazy(); return TRUE; } /***************************************************************************/ BOOL ClassColumnInfoBase :: GetDataTypeInfo(LONG iColumnNum, LPSQLTYPE &pSQLType) { if ( !Setup(iColumnNum) ) return FALSE; pSQLType = pColumnInformation->GetDataTypeInfo(); return TRUE; } /***************************************************************************/ SWORD ClassColumnInfoBase :: GetColumnName(LONG iColumnNumber, LPSTR pColumnName, LPSTR pColumnAlias) { //Create a store for column name BSTR lpbString; //Now we want column number "iColumnNumber" CBString myString; if (fIs__Generic) { CBString myAlias; GetClassObject(iColumnNumber, myString, myAlias); lpbString = myString.GetString(); //Copy across alias if (pColumnAlias) { pColumnAlias[0] = 0; //RAID 42256 char* pTemp = (char*) pColumnAlias; _bstr_t myValue((BSTR)myAlias.GetString()); Utility_WideCharToDBCS(myValue, &pTemp, MAX_COLUMN_NAME_LENGTH); pColumnAlias[MAX_COLUMN_NAME_LENGTH] = 0; } } else { if ( FAILED(SafeArrayGetElement(rgSafeArray, &iColumnNumber, &lpbString)) ) { return SQL_ERROR; } } //copy column name pColumnName[0] = 0; //RAID 42256 char* pTemp = (char*) pColumnName; _bstr_t myValue((BSTR)lpbString); Utility_WideCharToDBCS(myValue, &pTemp, MAX_COLUMN_NAME_LENGTH); pColumnName[MAX_COLUMN_NAME_LENGTH] = 0; //SAI ADDED if (!fIs__Generic) SysFreeString(lpbString); return SQL_SUCCESS; } /***************************************************************************/ // Checked for SetInterfaceSecurityEx on IWbemServices UWORD ClassColumnInfoBase ::Get__GenericProfile() { UWORD propertyCount = cColumnDefs; SAFEARRAY FAR* rgSafeArrayExtra = NULL; //Get the names of the non-system properties/columns SCODE scT = pTableDef->pSingleTable->GetNames ( NULL, WBEM_FLAG_NONSYSTEM_ONLY, NULL, &rgSafeArrayExtra ); if (FAILED(scT)) { rgSafeArrayExtra = NULL; return cColumnDefs; } //Lower bound LONG iLBoundExtra; //Upper bound LONG iUBoundExtra; SafeArrayGetLBound(rgSafeArrayExtra, 1, &iLBoundExtra ); SafeArrayGetUBound(rgSafeArrayExtra, 1, &iUBoundExtra ); UWORD cNumColumnDefs = (UWORD) (iUBoundExtra - iLBoundExtra + 1); //As we know the total number of properties (cColumnDefs) //and the total number of non-system properties (cNumColumnDefs) //we can calculate the number of system properties cSystemProperties = cColumnDefs - cNumColumnDefs; embedded = new CEmbeddedDataItems* [cNumColumnDefs]; embeddedSize = cNumColumnDefs; for (long i = 0; i < embeddedSize; i++) { embedded[i] = new CEmbeddedDataItems(); } //Update number of columns (from ISAMTableDef) if (pTableDef && pTableDef->passthroughMap) { cColumnDefs = (UWORD) pTableDef->passthroughMap->GetCount(); } for (i = 0; i < cNumColumnDefs; i++) { //Create a store for column name BSTR lpbString; //Now we want column number "i" if ( FAILED(SafeArrayGetElement(rgSafeArrayExtra, &i, &lpbString)) ) { return cColumnDefs; } //Get the property type and value CIMTYPE vType; VARIANT pVal; if ( FAILED(pTableDef->pSingleTable->Get(lpbString, 0, &pVal, &vType, 0)) ) { return cColumnDefs; } //We are looking for embedded objects if (vType == CIM_OBJECT) { (embedded[i])->embeddedName = lpbString; IWbemClassObject* myEmbeddedObj = NULL; IUnknown* myUnk = pVal.punkVal; //(5) myUnk->QueryInterface(IID_IWbemClassObject, (void**)&myEmbeddedObj); if (myEmbeddedObj) { //Get the __CLASS property //Get the property type and value VARIANT pVal2; CBString cimClass(L"__CLASS", FALSE); if ( SUCCEEDED(myEmbeddedObj->Get(cimClass.GetString(), 0, &pVal2, NULL, 0)) ) { _bstr_t wEmbeddedClassName = pVal2.bstrVal; (embedded[i])->cClassObject = NULL; IWbemServicesPtr myServicesPtr = NULL; ISAMGetIWbemServices(pTableDef->lpISAM, *(pTableDef->pGateway2), myServicesPtr); myServicesPtr->GetObject(wEmbeddedClassName, 0, pTableDef->pContext, &((embedded[i])->cClassObject), NULL); VariantClear(&pVal2); } myEmbeddedObj->Release(); } VariantClear(&pVal); } SysFreeString(lpbString); } //Tidy Up SafeArrayDestroy(rgSafeArrayExtra); return propertyCount; } /***************************************************************************/ IWbemClassObject* ClassColumnInfoBase :: GetClassObject(LONG iColumnNumber, CBString& lpPropName, CBString& cbTableAlias) { //Examine the zero-based column number and return the //parent class object containing the requested property if (pTableDef->passthroughMap) { PassthroughLookupTable* passthroughElement = NULL; WORD myIndex = (WORD)iColumnNumber; BOOL status = pTableDef->passthroughMap->Lookup(myIndex, (void*&)passthroughElement); if (status) { lpPropName.AddString(passthroughElement->GetColumnName(), FALSE); char* lpTableAlias = passthroughElement->GetTableAlias(); if (!lpTableAlias || !strlen(lpTableAlias)) return NULL; cbTableAlias.AddString(lpTableAlias, FALSE); //Now get the class object UWORD cNumColumnDefs = cColumnDefs; //(as this value has been updated) UWORD index = 0; while (index < cNumColumnDefs) { if ((embedded[index])->embeddedName.GetString()) { if (_wcsicmp((embedded[index])->embeddedName.GetString(), cbTableAlias.GetString()) == 0) { //found embedded object return ((embedded[index])->cClassObject); } } index++; } } } //should not reach here return NULL; } /***************************************************************************/ SWORD ClassColumnInfoBase :: GetColumnInfo(LONG iColumnNumber) { //Create a store for column name BSTR lpbString; IWbemClassObjectPtr parentClass = NULL; CBString myString; if (fIs__Generic) { CBString myAlias; //not used parentClass = GetClassObject(iColumnNumber, myString, myAlias); lpbString = myString.GetString(); } else { parentClass = pTableDef->pSingleTable; //Now we want column number "iColumnNumber" if ( FAILED(SafeArrayGetElement(rgSafeArray, &iColumnNumber, &lpbString)) ) { return SQL_ERROR; } } #ifdef TESTING //copy column name char pColumnName [MAX_COLUMN_NAME_LENGTH+1]; pColumnName[0] = 0; wcstombs(pColumnName, lpbString, MAX_COLUMN_NAME_LENGTH); pColumnName[MAX_COLUMN_NAME_LENGTH] = 0; #endif //Get the "Type" value CIMTYPE pColumnType; if ( FAILED(parentClass->Get(lpbString, 0, NULL, &pColumnType, 0)) ) { if (!fIs__Generic) SysFreeString(lpbString); return SQL_ERROR; } //flag to indicate if property is marked 'lazy' BOOL fIsLazyProperty = FALSE; //Now get the qualifiers (if available) IWbemQualifierSetPtr pQualifierSet = NULL; if ( S_OK != (parentClass->GetPropertyQualifierSet (lpbString, &pQualifierSet)) ) { if (!fIs__Generic) SysFreeString(lpbString); //No qualifers, therefore no CIMTYPE, MAX & LAZY qualifiers pColumnInformation = new ClassColumnInfo(pColumnType, NULL, NULL, FALSE, fIsLazyProperty); return SQL_SUCCESS; } //Get the lazy qualifer (if applicable) VARIANT pValLazy; BSTR lazyStr = SysAllocString(WBEMDR32_L_LAZY); if ( S_OK == (pQualifierSet->Get(lazyStr, 0, &pValLazy, NULL)) ) { fIsLazyProperty = TRUE; VariantClear(&pValLazy); } else { fIsLazyProperty = FALSE; } SysFreeString(lazyStr); VARIANT pVal; //Get the CIMTYPE qualifier BSTR cimTypeStr = SysAllocString(WBEMDR32_L_CIMTYPE); if ( S_OK != (pQualifierSet->Get(cimTypeStr, 0, &pVal, NULL)) ) { //No CIMTYPE qualifier (therefore no max string) pColumnInformation = new ClassColumnInfo(pColumnType, NULL,//&pVal NULL, FALSE, fIsLazyProperty); } else { //Got the CIMTYPE qualifier //Now get the optional MAX qualifier long cbMaxValue = 0; VARIANT pVal2; BSTR maxStr = SysAllocString(WBEMDR32_L_MAX); if ( S_OK != (pQualifierSet->Get(maxStr, 0, &pVal2, NULL)) ) { //Got CIMTYPE but no MAX qualifier pColumnInformation = new ClassColumnInfo(pColumnType, &pVal, NULL, TRUE, fIsLazyProperty); } else { //Got CIMTYPE and got MAX qualifier SDWORD maxLenVal = pVal2.iVal; pColumnInformation = new ClassColumnInfo(pColumnType, &pVal, maxLenVal, TRUE, fIsLazyProperty); VariantClear(&pVal2); } SysFreeString(maxStr); VariantClear(&pVal); } SysFreeString(cimTypeStr); if (!fIs__Generic) SysFreeString(lpbString); return SQL_SUCCESS; } /***************************************************************************/ SWORD ClassColumnInfoBase :: GetKey(LONG iColumnNumber, BOOL &isAKey) { //We return FALSE for now as we don't support SQLPrimaryKeys //If we do implement SQLPrimaryKeys we can comment out the next two lines isAKey = FALSE; return SQL_SUCCESS; //Create a store for column name BSTR lpbString; //Now we want column number "iColumnNumber" if ( FAILED(SafeArrayGetElement(rgSafeArray, &iColumnNumber, &lpbString)) ) { return SQL_ERROR; } //Now get the Key attribute value (if available) IWbemQualifierSetPtr pQualifierSet = NULL; if ( S_OK != (pTableDef->pSingleTable->GetPropertyQualifierSet (lpbString, &pQualifierSet)) ) { SysFreeString(lpbString); return SQL_ERROR; } //SAI ADDED - Tidy up SysFreeString(lpbString); lpbString = NULL; //Now get the KEY attribute value (if available) VARIANT pVal; isAKey = FALSE; BSTR keyBSTR = SysAllocString(WBEMDR32_L_KEY); if ( S_OK == (pQualifierSet->Get(keyBSTR, 0, &pVal, NULL)) ) { isAKey = (pVal.boolVal != 0) ? TRUE : FALSE; //TidyUp VariantClear(&pVal); } SysFreeString(keyBSTR); return SQL_SUCCESS; } /***************************************************************************/ SWORD ClassColumnInfoBase :: GetColumnAttr(LONG iColumnNumber, LPSTR pAttrStr, SDWORD cbValueMax, SDWORD &cbBytesCopied) { SWORD err = SQL_SUCCESS; cbBytesCopied = 0; //Create a store for column name BSTR lpbString; //Now we want column number "iColumnNumber" if ( FAILED(SafeArrayGetElement(rgSafeArray, &iColumnNumber, &lpbString)) ) { return SQL_ERROR; } #ifdef TESTING //copy column name char pColumnName [MAX_COLUMN_NAME_LENGTH+1]; pColumnName[0] = 0; wcstombs(pColumnName, lpbString, MAX_COLUMN_NAME_LENGTH); pColumnName[MAX_COLUMN_NAME_LENGTH] = 0; #endif //Get attributes for chosen column IWbemQualifierSetPtr pQualifierSet = NULL; if ( S_OK != (pTableDef->pSingleTable->GetPropertyQualifierSet(lpbString, &pQualifierSet)) ) { SysFreeString(lpbString); return SQL_ERROR; } SysFreeString(lpbString); lpbString = NULL; //Get CIMTYPE String VARIANT pVal2; BSTR syntaxStr = NULL; BOOL fClearpVal2 = FALSE; BSTR cimTypeBSTR = SysAllocString(WBEMDR32_L_CIMTYPE); if ( S_OK == (pQualifierSet->Get(cimTypeBSTR, 0, &pVal2, NULL)) ) { if (pVal2.bstrVal) syntaxStr = pVal2.bstrVal; fClearpVal2 = TRUE; } SysFreeString(cimTypeBSTR); //Get the MAX String VARIANT pVal3; SDWORD maxLenVal = 0; BOOL fClearpVal3 = FALSE; BSTR maxBSTR = SysAllocString(WBEMDR32_L_MAX); if ( S_OK == (pQualifierSet->Get(maxBSTR, 0, &pVal3, NULL)) ) { maxLenVal = pVal3.iVal; fClearpVal3 = TRUE; } SysFreeString(maxBSTR); //Now get list of attribute names from attribute set //create SAFEARRAY to store attribute names SAFEARRAY FAR* rgNames = NULL; //Fetch attribute names pQualifierSet->GetNames(0, &rgNames); SafeArrayLock(rgNames); //Get the upper and lower bounds of SAFEARRAY long lowerBound; SafeArrayGetLBound(rgNames, 1, &lowerBound); long upperBound; SafeArrayGetUBound(rgNames, 1, &upperBound); //Get each name out BSTR pTheAttrName; for (long ix = lowerBound; ix <= upperBound; ix++) { if ( SUCCEEDED(SafeArrayGetElement(rgNames, &ix, &pTheAttrName)) ) { //Get variant value of named attribute VARIANT pVal; if ( S_OK == (pQualifierSet->Get(pTheAttrName, 0, &pVal, NULL)) ) { //Decode variant value, as we do not know actual size of value //beforehand we will create buffers in increments of 200 bytes //until we can get the value with truncation ULONG cwAttemptToGetValue = 0; ULONG wBufferLen = 0; char* buffer = NULL; SDWORD cbValue; SWORD err = ISAM_TRUNCATION; while ( err == ISAM_TRUNCATION ) { if (buffer) delete buffer; wBufferLen = 200 * (++cwAttemptToGetValue); buffer = new char [wBufferLen + 1]; buffer[0] = 0; err = ISAMGetValueFromVariant(pVal, SQL_C_CHAR, buffer, wBufferLen, &cbValue, 0, syntaxStr, maxLenVal); } VariantClear (&pVal); if (fClearpVal2) VariantClear (&pVal2); if (fClearpVal3) VariantClear (&pVal3); //Check for error if (err != NO_ISAM_ERR) { pTableDef->lpISAM->errcode = err; SafeArrayUnlock(rgNames); SafeArrayDestroy(rgNames); SysFreeString(pTheAttrName); delete buffer; return SQL_ERROR; } //Once we have the name and value of the attribute let us try and add //it to the output buffer //First try and save the attribute name //Save old number of bytes copied so that if truncation //occurs we can roll back to original state SDWORD pdbOldValue = cbBytesCopied; //If this is not the first attribute in the list //we must separate the attribute/value pairs with "\n" character if ( (cbValueMax - cbBytesCopied) && cbBytesCopied) { pAttrStr[cbBytesCopied++] = '\n'; } //Now add in attribute name //first convert it from a BSTR to a char* char* lpTheAttrString = NULL; ULONG cLength = 0; if (pTheAttrName) { cLength = wcslen(pTheAttrName); lpTheAttrString = new char [cLength + 1]; lpTheAttrString[0] = 0; wcstombs(lpTheAttrString, pTheAttrName, cLength); lpTheAttrString[cLength] = 0; } BOOL fOutOfBufferSpace = FALSE; err = ISAMFormatCharParm (lpTheAttrString, fOutOfBufferSpace, pAttrStr, cbValueMax, &cbBytesCopied, FALSE); delete lpTheAttrString; //Now add in value if (err == NO_ISAM_ERR) { err = ISAMFormatCharParm (buffer, fOutOfBufferSpace, pAttrStr, cbValueMax, &cbBytesCopied, FALSE); } delete buffer; buffer = NULL; if (err != NO_ISAM_ERR) { //Truncation took place so rollback cbBytesCopied = pdbOldValue; //Null terminate pAttrStr[cbBytesCopied] = 0; SafeArrayUnlock(rgNames); SafeArrayDestroy(rgNames); SysFreeString(pTheAttrName); return SQL_SUCCESS_WITH_INFO; } //Null terminate pAttrStr[cbBytesCopied] = 0; } else { //Error, tidy up and then quit SysFreeString(pTheAttrName); SafeArrayUnlock(rgNames); SafeArrayDestroy(rgNames); return SQL_ERROR; } SysFreeString(pTheAttrName); } else { //Error, tidy up and then quit SafeArrayUnlock(rgNames); SafeArrayDestroy(rgNames); return SQL_ERROR; } } //Tidy Up SafeArrayUnlock(rgNames); SafeArrayDestroy(rgNames); return SQL_SUCCESS; } /***************************************************************************/ SWORD INTFUNC ISAMGetTableAttr(LPISAMTABLEDEF lpISAMTableDef, LPSTR pAttrStr, SDWORD cbValueMax, SDWORD &cbBytesCopied) { SWORD err = SQL_SUCCESS; cbBytesCopied = 0; //Get attributes for chosen table IWbemQualifierSetPtr pQualifierSet = NULL; if ( S_OK != (lpISAMTableDef->pSingleTable->GetQualifierSet(&pQualifierSet)) ) { return SQL_ERROR; } //Now get list of attribute names from attribute set //create SAFEARRAY to store attribute names SAFEARRAY FAR* rgNames = NULL; //Fetch attribute names pQualifierSet->GetNames(0, &rgNames); SafeArrayLock(rgNames); //Get the upper and lower bounds of SAFEARRAY long lowerBound; SafeArrayGetLBound(rgNames, 1, &lowerBound); long upperBound; SafeArrayGetUBound(rgNames, 1, &upperBound); //Get each name out BSTR pTheAttrName; for (long ix = lowerBound; ix <= upperBound; ix++) { if ( SUCCEEDED(SafeArrayGetElement(rgNames, &ix, &pTheAttrName)) ) { //Get variant value of named attribute VARIANT pVal; if ( S_OK == (pQualifierSet->Get(pTheAttrName, 0, &pVal, NULL)) ) { //Get attribute set for column IWbemQualifierSetPtr pQualifierSet2 = NULL; if ( S_OK != (lpISAMTableDef->pSingleTable->GetPropertyQualifierSet(pTheAttrName, &pQualifierSet2)) ) { SysFreeString(pTheAttrName); return SQL_ERROR; } //Get CIMTYPE String VARIANT pVal2; BSTR syntaxStr = NULL; BOOL fClearpVal2 = FALSE; BSTR cimTypeBSTR = SysAllocString(WBEMDR32_L_CIMTYPE); if ( S_OK == (pQualifierSet2->Get(cimTypeBSTR, 0, &pVal2, NULL)) ) { if (pVal2.bstrVal) syntaxStr = pVal2.bstrVal; fClearpVal2 = TRUE; } SysFreeString(cimTypeBSTR); //Get the MAX String VARIANT pVal3; SDWORD maxLenVal = 0; BOOL fClearpVal3 = FALSE; BSTR maxBSTR = SysAllocString(WBEMDR32_L_MAX); if ( S_OK == (pQualifierSet->Get(maxBSTR, 0, &pVal3, NULL)) ) { maxLenVal = pVal3.iVal; fClearpVal3 = TRUE; } SysFreeString(maxBSTR); //Decode variant value, as we do not know actual size of value //beforehand we will create buffers in increments of 200 bytes //until we can get the value with truncation ULONG cwAttemptToGetValue = 0; ULONG wBufferLen = 0; char* buffer = NULL; SDWORD cbValue; SWORD err = ISAM_TRUNCATION; while ( err == ISAM_TRUNCATION ) { if (buffer) delete buffer; wBufferLen = 200 * (++cwAttemptToGetValue); buffer = new char [wBufferLen + 1]; buffer[0] = 0; err = ISAMGetValueFromVariant(pVal, SQL_C_CHAR, buffer, wBufferLen, &cbValue, 0, syntaxStr, maxLenVal); } VariantClear (&pVal); if (fClearpVal2) VariantClear (&pVal2); if (fClearpVal3) VariantClear (&pVal3); //Check for error if (err != NO_ISAM_ERR) { lpISAMTableDef->lpISAM->errcode = err; SafeArrayUnlock(rgNames); SafeArrayDestroy(rgNames); SysFreeString(pTheAttrName); delete buffer; return SQL_ERROR; } //Once we have the name and value of the attribute let us try and add //it to the output buffer //First try and save the attribute name //Save old number of bytes copied so that if truncation //occurs we can roll back to original state SDWORD pdbOldValue = cbBytesCopied; //If this is not the first attribute in the list //we must separate the attribute/value pairs with "\n" character if ( (cbValueMax - cbBytesCopied) && cbBytesCopied) { pAttrStr[cbBytesCopied++] = '\n'; } //Now add in attribute name //first convert it from a BSTR to a char* char* lpTheAttrString = NULL; ULONG cLength = 0; if (pTheAttrName) { cLength = wcslen(pTheAttrName); lpTheAttrString = new char [cLength + 1]; lpTheAttrString[0] = 0; wcstombs(lpTheAttrString, pTheAttrName, cLength); lpTheAttrString[cLength] = 0; } BOOL fOutOfBufferSpace = FALSE; err = ISAMFormatCharParm (lpTheAttrString, fOutOfBufferSpace, pAttrStr, cbValueMax, &cbBytesCopied, FALSE); delete lpTheAttrString; //Now add in value if (err == NO_ISAM_ERR) { err = ISAMFormatCharParm (buffer, fOutOfBufferSpace, pAttrStr, cbValueMax, &cbBytesCopied, FALSE); } delete buffer; buffer = NULL; if (err != NO_ISAM_ERR) { //Truncation took place so rollback cbBytesCopied = pdbOldValue; //Null terminate pAttrStr[cbBytesCopied] = 0; SysFreeString(pTheAttrName); return SQL_SUCCESS_WITH_INFO; } //Null terminate pAttrStr[cbBytesCopied] = 0; } else { //Error, tidy up and then quit SafeArrayUnlock(rgNames); SafeArrayDestroy(rgNames); return SQL_ERROR; } SysFreeString(pTheAttrName); } else { //Error, tidy up and then quit SafeArrayUnlock(rgNames); SafeArrayDestroy(rgNames); return SQL_ERROR; } } //Tidy Up SafeArrayUnlock(rgNames); SafeArrayDestroy(rgNames); return SQL_SUCCESS; } /***************************************************************************/ UWORD INTFUNC GetNumberOfColumnsInTable(LPISAMTABLEDEF lpISAMTableDef) { //Get number of columns ClassColumnInfoBase* cInfoBase = lpISAMTableDef->pColumnInfo; if ( !cInfoBase->IsValid() ) { return 0; } return cInfoBase->GetNumberOfColumns(); } /***************************************************************************/ /* This method checks if a string contains any */ /* character preference control characters */ /* such as %, _, \\ */ /* */ /* this method was cut and pasted out of an */ /* existing class and converted into a function */ static BOOL INTFUNC IsRegularExpression(char* lpPattern) { //First check if input string is valid and if it has any //characters to check for ULONG cLen = 0; char m_cWildcard = '%'; char m_cAnySingleChar = '_'; char m_cEscapeSeq = '\\'; if (lpPattern) cLen = strlen (lpPattern); ULONG iIndex = 0; if (cLen) { //Go through string checking for the 'wildcard' and 'single char' characters while (iIndex < cLen) { //Check for 'wildcard' and 'single char' characters if ( (lpPattern[iIndex] == m_cWildcard) || (lpPattern[iIndex] == m_cAnySingleChar) ) { return TRUE; } //Skip any characters which are preceeded by escape sequence character if ( lpPattern[iIndex] == m_cEscapeSeq) { //skip escape character and next one iIndex++; } //Increment index in string iIndex++; } } else { //No character to check return FALSE; } //If you reach here then input string must not be a regular expression return FALSE; } /***************************************************************************/ CNotifyTableNames ::CNotifyTableNames(LPISAMTABLELIST lpTblList) { //Initialize reference count and backpointer to table list m_cRef = 0; lpISAMTableList = lpTblList; //create mutex (no owed by anyone yet) m_mutex = CreateMutex(NULL, FALSE, NULL); } /***************************************************************************/ CNotifyTableNames :: ~CNotifyTableNames() { //Tidy Up CloseHandle(m_mutex); } /***************************************************************************/ STDMETHODIMP_(ULONG) CNotifyTableNames :: AddRef(void) { return ++m_cRef; } /***************************************************************************/ STDMETHODIMP_(ULONG) CNotifyTableNames :: Release(void) // FOLLOWUP: why is the decrement commented out? { // if (--m_cRef != 0) // { // return m_cRef; // } //If you reached this point the reference count is zero //Therefore we have got all information back lpISAMTableList->iIndex = lpISAMTableList->pTblList->GetHeadPosition(); lpISAMTableList->fGotAllInfo = TRUE; delete this; return 0; } /***************************************************************************/ STDMETHODIMP CNotifyTableNames :: QueryInterface(REFIID riid, LPVOID FAR* ppv) { *ppv = NULL; if (IID_IUnknown == riid || IID_IWbemObjectSink == riid) *ppv = this; if (*ppv == NULL) return ResultFromScode(E_NOINTERFACE); return NOERROR; } /***************************************************************************/ STDMETHODIMP_(SCODE) CNotifyTableNames :: Notify(long lObjectCount, IWbemClassObject** pObjArray) { //remember to mutex protect writing to table list WaitForSingleObject(m_mutex, INFINITE); for (long i = 0; i < lObjectCount; i++) { if (pObjArray[i]) { pObjArray[i]->AddRef(); lpISAMTableList->pTblList->AddTail(pObjArray[i]); } } ReleaseMutex(m_mutex); return WBEM_NO_ERROR; } /***************************************************************************/ /* Setups up ISAM structure which stores data-source information */ SWORD INTFUNC ISAMOpen(LPUSTR lpszServer, LPUSTR lpszDatabase, LPUSTR lpszDSN, // WBEM_LOGIN_AUTHENTICATION loginMethod, LPUSTR lpszUsername, LPUSTR lpszPassword, LPUSTR lpszLocale, LPUSTR lpszAuthority, BOOL fSysProps, CMapStringToOb *pNamespaceMap, LPISAM FAR *lplpISAM, LPUSTR lpszErrorMessage, BOOL fOptimization, BOOL fImpersonation, BOOL fPassthroughOnly, BOOL fIntpretEmptPwdAsBlk) { s_lstrcpy(lpszErrorMessage, ""); // ODBCTRACE("\nWBEM ODBC Driver : ISAMOpen\n"); //Extra check for table qualifier if (!lpszDatabase || !s_lstrlen (lpszDatabase)) // need to check in args here too { LoadString(s_hModule, ISAM_NS_QUALMISSING, (LPSTR)lpszErrorMessage, MAX_ERROR_LENGTH+1); *lplpISAM = NULL; return ISAM_NS_QUALMISSING; } HGLOBAL h; LPISAM lpISAM; h = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (ISAM)); if (h == NULL || (lpISAM = (LPISAM) GlobalLock (h)) == NULL) { if (h) GlobalFree(h); LoadString(s_hModule, ISAM_MEMALLOCFAIL, (LPSTR)lpszErrorMessage, MAX_ERROR_LENGTH+1); *lplpISAM = NULL; return ISAM_MEMALLOCFAIL; } lpISAM->cSQLTypes = NumTypes(); lpISAM->SQLTypes = SQLTypes; lpISAM->fTxnCapable = SQL_TC_NONE; lpISAM->fSchemaInfoTransactioned = FALSE; lpISAM->fMultipleActiveTxn = FALSE; lpISAM->fTxnIsolationOption = SQL_TXN_READ_UNCOMMITTED; lpISAM->fDefaultTxnIsolation = SQL_TXN_READ_UNCOMMITTED; lpISAM->udwNetISAMVersion = 0; lpISAM->hKernelApi = LoadLibrary("KERNEL32.DLL"); lpISAM->netConnection = NULL; lpISAM->netISAM = NET_OPAQUE_INVALID; lpISAM->fCaseSensitive = FALSE; s_lstrcpy(lpISAM->szName, ""); s_lstrcpy(lpISAM->szVersion, ""); lpISAM->cbMaxTableNameLength = 0; lpISAM->cbMaxColumnNameLength = 0; //WBEM Client Recognition variables //(dummy values which will be overridden) lpISAM->dwAuthLevel = 0; lpISAM->dwImpLevel = 0; lpISAM->gpAuthIdentity = NULL; lpISAM->pNamespaceMap = pNamespaceMap; s_lstrcpy (lpISAM->szServer, lpszServer); s_lstrcpy (lpISAM->szDatabase, lpszDatabase); s_lstrcpy (lpISAM->szUser, lpszUsername); s_lstrcpy (lpISAM->szPassword, lpszPassword); s_lstrcpy (lpISAM->szRootDb, "root"); //Flags for cloaking lpISAM->fIsLocalConnection = IsLocalServer((LPSTR) lpszServer); lpISAM->fW2KOrMore = IsW2KOrMore(); //Make copies of locale and authority lpISAM->m_Locale = NULL; if (lpszLocale) { int localeLen = lstrlen((char*)lpszLocale); lpISAM->m_Locale = new char [localeLen + 1]; (lpISAM->m_Locale)[0] = 0; lstrcpy(lpISAM->m_Locale, (char*)lpszLocale); } lpISAM->m_Authority = NULL; if (lpszAuthority) { int authLen = lstrlen((char*)lpszAuthority); lpISAM->m_Authority = new char [authLen + 1]; (lpISAM->m_Authority)[0] = 0; lstrcpy(lpISAM->m_Authority, (char*)lpszAuthority); } lpISAM->fOptimization = fOptimization; lpISAM->fSysProps = fSysProps; lpISAM->fPassthroughOnly = fPassthroughOnly; lpISAM->fIntpretEmptPwdAsBlank = fIntpretEmptPwdAsBlk; //Check if impersonation is requested lpISAM->Impersonate = NULL; if (fImpersonation) { //Now check if impersonation is necessary //only if connecting locally if (IsLocalServer((LPSTR) lpszServer)) { lpISAM->Impersonate = new ImpersonationManager(lpISAM->szUser, lpISAM->szPassword, lpISAM->m_Authority); } else { ODBCTRACE("\nWBEM ODBC Driver : Server not detected as local, not impersonating\n"); } } lpISAM->errcode = NO_ISAM_ERR; //SAI new - make sure there is nothing in old //ISAM before you assign to it if (*lplpISAM) ISAMClose(*lplpISAM); *lplpISAM = lpISAM; //Check if impersonation worked if (fImpersonation && lpISAM->Impersonate) { if ( ! lpISAM->Impersonate->CanWeImpersonate() ) { lpISAM->pNamespaceMap = NULL; //protect against deleting namespace map ISAMClose(lpISAM); *lplpISAM = NULL; return ISAM_ERROR; } } return NO_ISAM_ERR; } /***************************************************************************/ /* Creates a communication channel to the Gateway Server */ // Checked for SetInterfaceSecurityEx on IWbemServices void INTFUNC ISAMGetGatewayServer(IWbemServicesPtr& pGateway, LPISAM lpISAM, LPUSTR lpQualifierName, SWORD cbQualifierName) { ThreadLocaleIdManager myThread(lpISAM); //First get the locator interface IWbemLocator* pLocator = NULL; SCODE sc = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER , IID_IWbemLocator, (void**) (&pLocator) ); //Bug fix for dbWeb if ( FAILED(sc) ) { //If you fail, initialize OLE and try again OleInitialize(0); sc = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER , IID_IWbemLocator, (void**) (&pLocator) ); } if ( FAILED(sc) ) { ODBCTRACE("\nWBEM ODBC Driver : ISAMGetGatewayServer version 2 : Error position 1\n"); return; } //Get user and password fields //Get handle to gateway server interface pGateway = NULL; long refcount = 0; //Check if we want the default database or something else //We will be building the fully qualified database pathname //so we work out some lengths first SWORD cbServerLen = (SWORD) _mbstrlen((LPSTR)lpISAM->szServer); //RAID 57673 WMI has changed such that if you //connect locally and pass a username and password //it will fail //Check for local connection // CBString myServerStr; // myServerStr.AddString( (LPSTR)lpISAM->szServer, FALSE ); // CServerLocationCheck myCheck (myServerStr); BOOL fIsLocalConnection = lpISAM->fIsLocalConnection;//myCheck.IsLocal(); //Used to store the fully qualified database pathname wchar_t pWcharName [MAX_DATABASE_NAME_LENGTH+1]; pWcharName[0] = 0; if (cbQualifierName) { //We want something else //We need to prepend server name to qualifier name //Need to make sure everything fits in buffer size if ( (cbServerLen + cbQualifierName + 1) > MAX_DATABASE_NAME_LENGTH ) { pLocator->Release(); ODBCTRACE("\nWBEM ODBC Driver : ISAMGetGatewayServer version 2 : Error position 2\n"); return; } CBString namespaceBSTR; //Construct string if (cbServerLen) { char pCharName [MAX_DATABASE_NAME_LENGTH+1]; pCharName[0] = 0; sprintf (pCharName, "%s\\%s", (LPUSTR)lpISAM->szServer, (LPSTR)lpQualifierName); CString myText; myText.Format("\nWBEM ODBC Driver : Connecting using : %s\n", pCharName); ODBCTRACE(myText); //Convert to wide string namespaceBSTR.AddString(pCharName, FALSE); } else { if (lpQualifierName) { namespaceBSTR.AddString((LPSTR)lpQualifierName, FALSE, cbQualifierName); } } //Convert wide characters to BSTR for DCOM //---------------------------------------- CBString userBSTR; if (!fIsLocalConnection) userBSTR.AddString((LPSTR)lpISAM->szUser, FALSE); CBString passwdBSTR; if (!fIsLocalConnection) passwdBSTR.AddString((LPSTR)lpISAM->szPassword, lpISAM->fIntpretEmptPwdAsBlank); CBString localeBSTR; CBString authorityBSTR; localeBSTR.AddString(lpISAM->m_Locale, FALSE); //Get the local and authority fields authorityBSTR.AddString(lpISAM->m_Authority, FALSE); sc = pLocator->ConnectServer (namespaceBSTR.GetString(), userBSTR.GetString(), passwdBSTR.GetString(), localeBSTR.GetString(), 0, authorityBSTR.GetString(), NULL, &pGateway); if (sc == S_OK) { sc = GetAuthImp( pGateway, &(lpISAM->dwAuthLevel), &(lpISAM->dwImpLevel)); if(sc == S_OK) { if (lpISAM->dwAuthLevel > RPC_C_AUTHN_LEVEL_NONE) lpISAM->dwImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE; if ( lpISAM->gpAuthIdentity ) { WbemFreeAuthIdentity( lpISAM->gpAuthIdentity ); lpISAM->gpAuthIdentity = NULL; } sc = ISAMSetCloaking1( pGateway, lpISAM->fIsLocalConnection, lpISAM->fW2KOrMore, lpISAM->dwAuthLevel, lpISAM->dwImpLevel, authorityBSTR.GetString(), userBSTR.GetString(), passwdBSTR.GetString(), &(lpISAM->gpAuthIdentity) ); /* if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(pGateway, lpISAM->dwAuthLevel, lpISAM->dwImpLevel); } else { sc = SetInterfaceSecurityEx(pGateway, authorityBSTR.GetString(), userBSTR.GetString(), passwdBSTR.GetString(), lpISAM->dwAuthLevel, lpISAM->dwImpLevel, EOAC_NONE, &(lpISAM->gpAuthIdentity), &gpPrincipal ); } */ } } } else { //We want the default database //Get default connection from LPISAM == \default //We need to prepend server name to \default //Need to make sure everything fits in buffer size SWORD cbRootLen = strlen ((LPSTR)lpISAM->szRootDb); if ( (cbServerLen + cbRootLen + 9) > MAX_DATABASE_NAME_LENGTH) { pLocator->Release(); ODBCTRACE("\nWBEM ODBC Driver : ISAMGetGatewayServer version 2 : Error position 3\n"); return; } //Construct string CBString namespaceBSTR; if (cbServerLen) { char pCharName [MAX_DATABASE_NAME_LENGTH+1]; pCharName[0] = 0; sprintf (pCharName, "%s\\%s\\default", (LPUSTR)lpISAM->szServer, (LPSTR)lpISAM->szRootDb); //Convert to wide string namespaceBSTR.AddString(pCharName, FALSE); } else { if ((LPSTR)lpISAM->szRootDb) { char pCharName [MAX_DATABASE_NAME_LENGTH+1]; pCharName[0] = 0; sprintf (pCharName, "%s\\default", (LPSTR)lpISAM->szRootDb); namespaceBSTR.AddString(pCharName, FALSE); } } //Convert wide characters to BSTR for DCOM //---------------------------------------- CBString userBSTR; if (!fIsLocalConnection) userBSTR.AddString((LPSTR)lpISAM->szUser, FALSE); CBString passwdBSTR; if (!fIsLocalConnection) passwdBSTR.AddString((LPSTR)lpISAM->szPassword, lpISAM->fIntpretEmptPwdAsBlank); CBString localeBSTR; CBString authorityBSTR; //Get the local and authority fields localeBSTR.AddString(lpISAM->m_Locale, FALSE); authorityBSTR.AddString(lpISAM->m_Authority, FALSE); sc = pLocator->ConnectServer (namespaceBSTR.GetString(), userBSTR.GetString(), passwdBSTR.GetString(), localeBSTR.GetString(), 0, authorityBSTR.GetString(), NULL, &pGateway); if (sc == S_OK) { sc = GetAuthImp( pGateway, &(lpISAM->dwAuthLevel), &(lpISAM->dwImpLevel)); if(sc == S_OK) { if (lpISAM->dwAuthLevel > RPC_C_AUTHN_LEVEL_NONE) lpISAM->dwImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE; if ( lpISAM->gpAuthIdentity ) { WbemFreeAuthIdentity( lpISAM->gpAuthIdentity ); lpISAM->gpAuthIdentity = NULL; } sc = ISAMSetCloaking1( pGateway, lpISAM->fIsLocalConnection, lpISAM->fW2KOrMore, lpISAM->dwAuthLevel, lpISAM->dwImpLevel, authorityBSTR.GetString(), userBSTR.GetString(), passwdBSTR.GetString(), &(lpISAM->gpAuthIdentity) ); /* if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(pGateway, lpISAM->dwAuthLevel, lpISAM->dwImpLevel); } else { sc = SetInterfaceSecurityEx(pGateway, authorityBSTR.GetString(), userBSTR.GetString(), passwdBSTR.GetString(), lpISAM->dwAuthLevel, lpISAM->dwImpLevel, EOAC_NONE, &(lpISAM->gpAuthIdentity), &gpPrincipal); } */ } } } //We have now finished with the locator so we can release it pLocator->Release(); if ( FAILED(sc) ) { ODBCTRACE("\nWBEM ODBC Driver : ISAMGetGatewayServer version 2 : Error position 4\n"); return; } } /***************************************************************************/ /* Creates a communication channel to the Gateway Server */ // Checked for SetInterfaceSecurityEx on IWbemServices void INTFUNC ISAMGetGatewayServer(IWbemServicesPtr& pGateway, LPUSTR lpServerName, // WBEM_LOGIN_AUTHENTICATION loginMethod, LPUSTR objectPath, LPUSTR lpUserName, LPUSTR lpPassword, LPUSTR lpLocale, LPUSTR lpAuthority, DWORD &dwAuthLevel, DWORD &dwImpLevel, BOOL fIntpretEmptPwdAsBlank, COAUTHIDENTITY** ppAuthIdent) { ThreadLocaleIdManager myThread(lpLocale); *ppAuthIdent = NULL; IWbemLocator* pLocator = NULL; SCODE sc = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER , IID_IWbemLocator, (void**) (&pLocator) ); if ( FAILED(sc) ) { ODBCTRACE("\nWBEM ODBC Driver : ISAMGetGatewayServer version 1 : Error position 1\n"); return; } pGateway = NULL; //SAI ADDED long refcount = 0; //We need to prepend server name to object path //Need to make sure everything fits in buffer size SWORD cbServerLen = 0; SWORD cbObjPathLen = 0; if (lpServerName) cbServerLen = (SWORD) _mbstrlen( (LPSTR)lpServerName); //RAID 57673 WMI has changed such that if you //connect locally and pass a username and password //it will fail //Check for local connection BOOL fIsLocalConnection = IsLocalServer((LPSTR) lpServerName); if (objectPath) cbObjPathLen = strlen ( (LPSTR)objectPath); if ( (cbServerLen + cbObjPathLen + 1) > MAX_DATABASE_NAME_LENGTH) { pLocator->Release(); ODBCTRACE("\nWBEM ODBC Driver : ISAMGetGatewayServer version 1 : Error position 2\n"); return; } //Construct string (namespace) CBString namespaceBSTR; if (cbServerLen) { char pCharBuff [MAX_DATABASE_NAME_LENGTH + 1]; pCharBuff[0] = 0; sprintf (pCharBuff, "%s\\%s", (LPUSTR)lpServerName, (LPSTR)objectPath); CString myText; myText.Format("\nWBEM ODBC Driver : Connecting using : %s\n", pCharBuff); ODBCTRACE(myText); //Convert to wide string namespaceBSTR.AddString(pCharBuff, FALSE); } else { if (objectPath) { namespaceBSTR.AddString((LPSTR)objectPath, FALSE); } } //Get user and password fields CBString localeBSTR; CBString authorityBSTR; localeBSTR.AddString((char*)lpLocale, FALSE); authorityBSTR.AddString((char*)lpAuthority, FALSE); //Convert wide characters to BSTR for DCOM //---------------------------------------- CBString userBSTR; if (!fIsLocalConnection) userBSTR.AddString((LPSTR)lpUserName, FALSE); CBString passwdBSTR; if (!fIsLocalConnection) passwdBSTR.AddString((LPSTR)lpPassword, fIntpretEmptPwdAsBlank); sc = pLocator->ConnectServer (namespaceBSTR.GetString(), userBSTR.GetString(), passwdBSTR.GetString(), localeBSTR.GetString(), 0, authorityBSTR.GetString(), NULL, &pGateway); if (sc == S_OK) { sc = GetAuthImp( pGateway, &dwAuthLevel, &dwImpLevel); if(sc == S_OK) { if (dwAuthLevel > RPC_C_AUTHN_LEVEL_NONE) dwImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE; sc = ISAMSetCloaking1( pGateway, fIsLocalConnection, IsW2KOrMore(), dwAuthLevel, dwImpLevel, authorityBSTR.GetString(), userBSTR.GetString(), passwdBSTR.GetString(), ppAuthIdent ); /* if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(pGateway, dwAuthLevel, dwImpLevel); } else { sc = SetInterfaceSecurityEx(pGateway, authorityBSTR.GetString(), userBSTR.GetString(), passwdBSTR.GetString(), dwAuthLevel, dwImpLevel, EOAC_NONE, ppAuthIdent, &gpPrincipal); } */ } } pLocator->Release(); if ( FAILED(sc) ) { ODBCTRACE("\nWBEM ODBC Driver : ISAMGetGatewayServer version 1 : Error position 3\n"); return; } } /***************************************************************************/ /* Function to fix MSQuery bug which appends */ /* a \ infront of _ characters in table names */ void ISAM_MSQueryBugFix(LPSTR lpOrigPattern, LPSTR lpNewPattern, SWORD &cbPattern) { SWORD iNewPatternIndex = 0; for (SWORD iIndex = 0; iIndex < cbPattern; iIndex++) { //Check for '\' character follwed by a '_' if ( (lpOrigPattern[iIndex] == '\\') && (lpOrigPattern[iIndex + 1] == '_') ) { //Skip underscore character iIndex++; } //Copy character lpNewPattern[iNewPatternIndex++] = lpOrigPattern[iIndex]; } //Null terminate new string lpNewPattern[iNewPatternIndex] = 0; //Update length of new string cbPattern = iNewPatternIndex; } /***************************************************************************/ /* Stores the necessary information to obtain a list of database tables */ /* with match the search pattern */ SWORD INTFUNC ISAMGetTableList (LPISAM lpISAM, LPUSTR lpPattern, SWORD cbPattern, LPUSTR lpQualifierName, SWORD cbQualifierName, LPISAMTABLELIST FAR *lplpISAMTableList, BOOL fWantSysTables, BOOL fEmptyList) { //Local Variables HGLOBAL h; LPISAMTABLELIST lpISAMTableList; lpISAM->errcode = NO_ISAM_ERR; //Allocate memory for table list structure on the heap h = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (ISAMTABLELIST)); if (h == NULL || (lpISAMTableList = (LPISAMTABLELIST) GlobalLock (h)) == NULL) { if (h) GlobalFree(h); lpISAM->errcode = ISAM_MEMALLOCFAIL; return ISAM_MEMALLOCFAIL; } //Check table name //There is a bug in MSQuery which appends extra \ character(s) //to table names which have underscore(s) //If this is the case we remove the \ character(s) char* lpNewPattern = new char [cbPattern + 1]; ISAM_MSQueryBugFix((LPSTR)lpPattern, lpNewPattern, cbPattern); //Copy search pattern _fmemcpy(lpISAMTableList->lpPattern, lpNewPattern, cbPattern); //Save search pattern length lpISAMTableList->cbPattern = cbPattern; //Delete tempory buffer delete lpNewPattern; //Copy qualifer name if it is non-null and not the default database lpISAMTableList->lpQualifierName[0] = 0; if (cbQualifierName) { strncpy((LPSTR)lpISAMTableList->lpQualifierName, (LPSTR)lpQualifierName, cbQualifierName); } else { cbQualifierName = 0; } lpISAMTableList->lpQualifierName[cbQualifierName] = 0; #ifdef TESTING //Remember to remove this printf printf ("Qualifier = %s", (char*)lpISAMTableList->lpQualifierName ); #endif //Is this table list going to be an empty one because //we requested a table type other than TABLE or SYSTEM TABLE ? lpISAMTableList->fEmptyList = fEmptyList; //Do we want System Tables ? lpISAMTableList->fWantSysTables = fWantSysTables; //Save the qualifier length lpISAMTableList->cbQualifierName = cbQualifierName; //Save flag to indicate if this is the first time table list is accessed lpISAMTableList->fFirstTime = TRUE; //Save information to create a context to database lpISAMTableList->lpISAM = lpISAM; //Initialize pointer to enumerated list of tables lpISAMTableList->pTblList = new CPtrList(); //Create an object to store WbemServices pointer lpISAMTableList->pGateway2 = new CSafeWbemServices(); //Setup output parameter *lplpISAMTableList = lpISAMTableList; lpISAMTableList->netISAMTableList = NET_OPAQUE_INVALID; return NO_ISAM_ERR; } /***************************************************************************/ /* Stores the necessary information to obtain a list of database qualifiers */ SWORD INTFUNC ISAMGetQualifierList(LPISAM lpISAM, LPISAMQUALIFIERLIST FAR *lplpISAMQualifierList) { //Local Variables HGLOBAL h; LPISAMQUALIFIERLIST lpISAMQualifierList; lpISAM->errcode = NO_ISAM_ERR; //Allocate memory for qualifier list structure on heap h = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (ISAMQUALIFIERLIST)); if (h == NULL || (lpISAMQualifierList = (LPISAMQUALIFIERLIST) GlobalLock (h)) == NULL) { if (h) GlobalFree(h); lpISAM->errcode = ISAM_MEMALLOCFAIL; return ISAM_MEMALLOCFAIL; } //Save flag to indicate if this is the first qualifier list is accessed lpISAMQualifierList->fFirstTime = TRUE; //Save information to create a context to database lpISAMQualifierList->lpISAM = lpISAM; //Setup output parameter *lplpISAMQualifierList = lpISAMQualifierList; return NO_ISAM_ERR; } /***************************************************************************/ /* Retrieves next table name from table list */ // Checked for SetInterfaceSecurityEx on IWbemServices SWORD INTFUNC ISAMGetNextTableName(UDWORD fSyncMode, LPISAMTABLELIST lpISAMTableList, LPUSTR lpTableName, LPUSTR lpTableType) { //Initialize, no errors found yet lpISAMTableList->lpISAM->errcode = NO_ISAM_ERR; IWbemClassObject* pSingleTable = NULL; BOOL fReleaseSingleTable = FALSE; //Check if we have detacted an empty table list due //to the fact that we requested a table type other than TABLE if (lpISAMTableList->fEmptyList) { lpISAMTableList->lpISAM->errcode = ISAM_EOF; return ISAM_EOF; } //We need to get the next table in the list from the LPISAMTABLELIST //However, if this is the first time this function is called, no table list //will be present, and we will need to get it from the Gateway Server // First time through? if (lpISAMTableList->fFirstTime) { //Clear out any old values if (lpISAMTableList->pTblList && lpISAMTableList->pTblList->GetCount()) { POSITION thePos = NULL; for ( thePos = lpISAMTableList->pTblList->GetHeadPosition(); thePos != NULL; ) { IWbemClassObject* pTheValue = (IWbemClassObject*) lpISAMTableList->pTblList->GetNext(thePos); pTheValue->Release(); } lpISAMTableList->pTblList->RemoveAll(); } //Initialize if (lpISAMTableList->pGateway2) lpISAMTableList->pGateway2->Invalidate(); lpISAMTableList->iIndex = NULL; lpISAMTableList->fFirstTime = FALSE; lpISAMTableList->fGotAllInfo = FALSE; //Get list of tables from the //Gateway Server which match search pattern //First get the Gateway Interface //remember to Release it after use lpISAMTableList->pGateway2->SetInterfacePtr (lpISAMTableList->lpISAM, (LPUSTR)lpISAMTableList->lpQualifierName, lpISAMTableList->cbQualifierName); //Check if a valid interface was returned if ( ! lpISAMTableList->pGateway2->IsValid() ) { //Could not create a Gateway Interface, return error lpISAMTableList->lpISAM->errcode = ISAM_PROVIDERFAIL; return ISAM_PROVIDERFAIL; } //First check if we need to get one table or a list of tables //by using the pattern matcher class if ( IsRegularExpression((char*)lpISAMTableList->lpPattern) ) { //We want a table LIST //We enumerate for tables, the resultant enumeration will be allocated on //the HEAP by the Gateway Server and referneced by pEnum BSTR emptySuperClass = SysAllocString(L""); //Check if we want to get list asynchronously if (fSyncMode == SQL_ASYNC_ENABLE_ON) { //Create notification object CNotifyTableNames* pNotifyTable = new CNotifyTableNames(lpISAMTableList); IWbemContext* pContext = ISAMCreateLocaleIDContextObject(lpISAMTableList->lpISAM->m_Locale); IWbemServicesPtr myServicesPtr = NULL; ISAMGetIWbemServices(lpISAMTableList->lpISAM, *(lpISAMTableList->pGateway2), myServicesPtr); //cloaking BOOL fIsLocalConnection = lpISAMTableList->lpISAM->fIsLocalConnection; if ( fIsLocalConnection && (lpISAMTableList->lpISAM->fW2KOrMore) ) { WbemSetDynamicCloaking(myServicesPtr, lpISAMTableList->lpISAM->dwAuthLevel, lpISAMTableList->lpISAM->dwImpLevel); } if ( FAILED(myServicesPtr->CreateClassEnumAsync (_bstr_t(), WBEM_FLAG_DEEP, pContext, pNotifyTable)) ) { //Tidy Up lpISAMTableList->pGateway2->Invalidate(); SysFreeString(emptySuperClass); if (pContext) pContext->Release(); //Flag error lpISAMTableList->lpISAM->errcode = ISAM_TABLELISTFAIL; return ISAM_TABLELISTFAIL; } //Tidy Up SysFreeString(emptySuperClass); if (pContext) pContext->Release(); //BREAK OUT OF THIS FUNCTION return ISAM_STILL_EXECUTING; } IEnumWbemClassObjectPtr pEnum = NULL; IWbemContext* pContext = ISAMCreateLocaleIDContextObject(lpISAMTableList->lpISAM->m_Locale); IWbemServicesPtr myServicesPtr = NULL; ISAMGetIWbemServices(lpISAMTableList->lpISAM, *(lpISAMTableList->pGateway2), myServicesPtr); //cloaking BOOL fIsLocalConnection = lpISAMTableList->lpISAM->fIsLocalConnection; if ( fIsLocalConnection && (lpISAMTableList->lpISAM->fW2KOrMore) ) { WbemSetDynamicCloaking(myServicesPtr, lpISAMTableList->lpISAM->dwAuthLevel, lpISAMTableList->lpISAM->dwImpLevel); } HRESULT hRes = myServicesPtr->CreateClassEnum (_bstr_t(), WBEM_FLAG_DEEP, pContext, &pEnum); if (pContext) pContext->Release(); ISAMSetCloaking2(pEnum, fIsLocalConnection, lpISAMTableList->lpISAM->fW2KOrMore, lpISAMTableList->lpISAM->dwAuthLevel, lpISAMTableList->lpISAM->dwImpLevel, lpISAMTableList->lpISAM->gpAuthIdentity); /* if ( fIsLocalConnection && (lpISAMTableList->lpISAM->fW2KOrMore) ) { WbemSetDynamicCloaking(pEnum, lpISAMTableList->lpISAM->dwAuthLevel, lpISAMTableList->lpISAM->dwImpLevel); } else { SetInterfaceSecurityEx(pEnum, lpISAMTableList->lpISAM->gpAuthIdentity, gpPrincipal, lpISAMTableList->lpISAM->dwAuthLevel, lpISAMTableList->lpISAM->dwImpLevel); } */ //Tidy Up SysFreeString(emptySuperClass); if (FAILED(hRes)) { //Tidy Up lpISAMTableList->pGateway2->Invalidate(); //Flag error lpISAMTableList->lpISAM->errcode = ISAM_TABLELISTFAIL; return ISAM_TABLELISTFAIL; } //Now we have the table enumeration get the first item ULONG puReturned; SCODE sc1 = pEnum->Reset(); SCODE sc2 = pEnum->Next(-1, 1, &pSingleTable, &puReturned); BOOL f1 = (S_OK == sc1) ? TRUE : FALSE; BOOL f2 = ( S_OK == sc2) ? TRUE : FALSE; if ( (pEnum == NULL) || (!f1) || (!f2) ) { //Tidy Up lpISAMTableList->pGateway2->Invalidate(); //Flag error lpISAMTableList->lpISAM->errcode = ISAM_EOF; return ISAM_EOF; } else { fReleaseSingleTable = TRUE; //Place any remaining tables in the pTblList IWbemClassObject* pSingleTable2 = NULL; while (S_OK == pEnum->Next(-1, 1, &pSingleTable2, &puReturned)) { lpISAMTableList->pTblList->AddTail(pSingleTable2); } //Set index to correct start position for next items lpISAMTableList->iIndex = lpISAMTableList->pTblList->GetHeadPosition(); } } else { //We want a SINGLE table //Set this flag in case you are asynchronously requesting //for 1 table !!! lpISAMTableList->fGotAllInfo = TRUE; //Create a pointer to store table class definition //the class definition object will be CREATED on the HEAP //by the GetClass function pSingleTable = NULL; LONG cLength = lstrlen((char*)lpISAMTableList->lpPattern); wchar_t* pWClassName = new wchar_t [cLength + 1]; pWClassName[0] = 0; int iItemsCopied = mbstowcs(pWClassName, (char*)lpISAMTableList->lpPattern, cLength); pWClassName[cLength] = 0; BSTR pTheTableName = SysAllocStringLen(pWClassName, cLength); IWbemContext* pContext = ISAMCreateLocaleIDContextObject(lpISAMTableList->lpISAM->m_Locale); IWbemServicesPtr myServicesPtr = NULL; ISAMGetIWbemServices(lpISAMTableList->lpISAM, *(lpISAMTableList->pGateway2), myServicesPtr); SCODE sStatus = myServicesPtr->GetObject(pTheTableName, 0, pContext, &pSingleTable, NULL); if (pContext) pContext->Release(); fReleaseSingleTable = TRUE; SysFreeString(pTheTableName); delete pWClassName; if ( FAILED(sStatus) || (!pSingleTable) ) { //Failed to get named class definition //Tidy Up lpISAMTableList->pGateway2->Invalidate(); //Flag error lpISAMTableList->lpISAM->errcode = ISAM_EOF; return ISAM_EOF; } } } else { //Get next item in enumeration if applicable //Check if function is asynchronous, if so //we must first check the fGotAllInfo flag //if we have all the info we can get the next table //we assign the pSingleTable pointer if ( (fSyncMode == SQL_ASYNC_ENABLE_ON) && (!lpISAMTableList->fGotAllInfo) ) return ISAM_STILL_EXECUTING; //Get Next if (lpISAMTableList->iIndex) { pSingleTable = (IWbemClassObject*)lpISAMTableList->pTblList->GetNext(lpISAMTableList->iIndex); } else { lpISAMTableList->lpISAM->errcode = ISAM_EOF; return ISAM_EOF; } } //Now we have the class definition object //for the next table let us get table name SWORD sc = S_OK; // ISAMGetNextTableName2(pSingleTable, fSyncMode, lpISAMTableList,lpTableName); //Because of stack overflow problems I have moved the //ISAMGetNextTableName2 code here BOOL fMatchingPattern = FALSE; do { //Now we have the class definition object //The table name is held in the property attribute __CLASS VARIANT grVariant; BSTR classBSTR = SysAllocString(WBEMDR32_L_CLASS); if (FAILED(pSingleTable->Get(classBSTR, 0, &grVariant, NULL, NULL))) { lpISAMTableList->lpISAM->errcode = ISAM_TABLENAMEFAIL; SysFreeString(classBSTR); sc = ISAM_TABLENAMEFAIL; } else { SysFreeString(classBSTR); /* Does this filename match the pattern? */ char pBuffer [MAX_TABLE_NAME_LENGTH+1]; pBuffer[0] = 0; wcstombs(pBuffer, grVariant.bstrVal, MAX_TABLE_NAME_LENGTH); pBuffer[MAX_TABLE_NAME_LENGTH] = 0; //Also do not add any class which starts with __ to table list //If you don't want SYSTEM TABLES if ( !PatternMatch(TRUE, (LPUSTR) pBuffer, SQL_NTS, (LPUSTR)lpISAMTableList->lpPattern, lpISAMTableList->cbPattern, ISAMCaseSensitive(lpISAMTableList->lpISAM)) || (!(lpISAMTableList->fWantSysTables) && !_strnicmp("__", pBuffer, 2)) ) { /* No. Get the next one */ VariantClear(&grVariant); //Get the next table here if (lpISAMTableList->iIndex) { if (fReleaseSingleTable) pSingleTable->Release(); pSingleTable = NULL; fReleaseSingleTable = FALSE; pSingleTable = (IWbemClassObject*)lpISAMTableList->pTblList->GetNext(lpISAMTableList->iIndex); } else { lpISAMTableList->lpISAM->errcode = ISAM_EOF; return ISAM_EOF; } } else { /* Return the name found */ lpTableName[0] = 0; //RAID 42256 char* pTemp = (char*) lpTableName; _bstr_t myValue((BSTR)grVariant.bstrVal); Utility_WideCharToDBCS(myValue, &pTemp, MAX_TABLE_NAME_LENGTH); lpTableName[MAX_TABLE_NAME_LENGTH] = 0; VariantClear(&grVariant); fMatchingPattern = TRUE; //to break out of loop sc = NO_ISAM_ERR; } } } while (!fMatchingPattern); //Setup table type, either SYSTEM TABLE or TABLE if (sc == NO_ISAM_ERR) { lpTableType[0] = 0; if (lpTableName && strlen((LPSTR)lpTableName) && (_strnicmp("__", (LPSTR)lpTableName, 2) == 0)) { s_lstrcpy(lpTableType, "SYSTEM TABLE"); } else { s_lstrcpy(lpTableType, "TABLE"); } } //We have finished with interfaces //so release them if (fReleaseSingleTable) pSingleTable->Release(); return sc; } /***************************************************************************/ /* Retrieves next qualifier name from qualifier list */ SWORD INTFUNC ISAMGetNextQualifierName(UDWORD fSyncMode, LPISAMQUALIFIERLIST lpISAMQualifierList, LPUSTR lpQualifierName) { //Initialize, no errors found yet lpISAMQualifierList->lpISAM->errcode = NO_ISAM_ERR; //We need to get the next qualifier in the list from the LPISAMQUALIFIERLIST //However, if this is the first time this function is called, no qualifier list //will be present, and we will need to get it // First time through? if (lpISAMQualifierList->fFirstTime) { //Initialize lpISAMQualifierList->iIndex = NULL; lpISAMQualifierList->fFirstTime = FALSE; //Get list of qualifiers from the //Gateway Server, this maps to getting a list //of namespaces. However, this list is already held in the //ISAM structure, so we simply extract from there //All we need to do is setup the correct position within the list //Setup first position in qualifier list lpISAMQualifierList->iIndex = lpISAMQualifierList->lpISAM->pNamespaceMap->GetStartPosition(); } //Get the next qualifier (namespace) return ISAMGetNextQualifierName2(lpISAMQualifierList, lpQualifierName); } /***************************************************************************/ /* This is the second phase of getting the next qualifier name */ /* This function is called when we have got all the information back */ /* from the MO Server */ SWORD INTFUNC ISAMGetNextQualifierName2(LPISAMQUALIFIERLIST lpISAMQualifierList, LPUSTR lpQualifierName) { //Now we have the namespace list, we need to get the 'iIndex' item for the next qualifier //If the 'iIndex' item is NULL we have reached the end of the list CString key; CNamespace* pN; CString pStr; if (lpISAMQualifierList->iIndex) { lpISAMQualifierList->lpISAM->pNamespaceMap->GetNextAssoc(lpISAMQualifierList->iIndex, key, (CObject* &)pN); pStr = pN->GetName(); } else { lpISAMQualifierList->lpISAM->errcode = ISAM_EOF; return ISAM_EOF; } //Return Qualifier name lpQualifierName[0] = 0; s_lstrcpy (lpQualifierName, pStr); return NO_ISAM_ERR; } /***************************************************************************/ /* Frees the table list stored in the LPISAMTABLELIST structure */ SWORD INTFUNC ISAMFreeTableList(LPISAMTABLELIST lpISAMTableList) { lpISAMTableList->lpISAM->errcode = NO_ISAM_ERR; if (lpISAMTableList->pTblList) { if (lpISAMTableList->pTblList->GetCount()) { POSITION thePos = NULL; for ( thePos = lpISAMTableList->pTblList->GetHeadPosition(); thePos != NULL; ) { IWbemClassObject* pTheValue = (IWbemClassObject*) lpISAMTableList->pTblList->GetNext(thePos); pTheValue->Release(); } lpISAMTableList->pTblList->RemoveAll(); } delete lpISAMTableList->pTblList; lpISAMTableList->pTblList = NULL; } if (lpISAMTableList->pGateway2) { delete lpISAMTableList->pGateway2; lpISAMTableList->pGateway2 = NULL; } GlobalUnlock (GlobalPtrHandle(lpISAMTableList)); GlobalFree (GlobalPtrHandle(lpISAMTableList)); return NO_ISAM_ERR; } /***************************************************************************/ /* Frees the qualifier list stored in the LPISAMQUALIFIERLIST structure */ SWORD INTFUNC ISAMFreeQualifierList(LPISAMQUALIFIERLIST lpISAMQualifierList) { lpISAMQualifierList->lpISAM->errcode = NO_ISAM_ERR; //Initialize lpISAMQualifierList->iIndex = NULL; GlobalUnlock (GlobalPtrHandle(lpISAMQualifierList)); GlobalFree (GlobalPtrHandle(lpISAMQualifierList)); return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMForeignKey(LPISAM lpISAM, LPUSTR lpszPrimaryKeyTableName, LPUSTR lpszForeignKeyTableName, LPUSTR lpPrimaryKeyName, LPUSTR lpForeignKeyName, SWORD FAR *lpfUpdateRule, SWORD FAR *lpfDeleteRule, UWORD FAR *lpcISAMKeyColumnList, LPISAMKEYCOLUMNNAME ISAMPrimaryKeyColumnList, LPISAMKEYCOLUMNNAME ISAMForeignKeyColumnList) { /* Never any foreign keys */ return ISAM_EOF; } /***************************************************************************/ SWORD INTFUNC ISAMCreateTable(LPISAM lpISAM, LPUSTR lpszTableName, LPISAMTABLEDEF FAR *lplpISAMTableDef) { return ISAM_NOTSUPPORTED; } /***************************************************************************/ SWORD INTFUNC ISAMAddColumn(LPISAMTABLEDEF lpISAMTableDef, LPUSTR lpszColumnName, UWORD iSqlType, UDWORD udParam1, UDWORD udParam2) { return ISAM_NOTSUPPORTED; } /***************************************************************************/ SWORD INTFUNC ISAMCreateIndex(LPISAMTABLEDEF lpISAMTableDef, LPUSTR lpszIndexName, BOOL fUnique, UWORD count, UWORD FAR *icol, BOOL FAR *fDescending) { return ISAM_NOTSUPPORTED; } /***************************************************************************/ SWORD INTFUNC ISAMDeleteIndex(LPISAM lpISAM, LPUSTR lpszIndexName) { return ISAM_NOTSUPPORTED; } /***************************************************************************/ /* Opens a specific table and produces a table definition to clearly define the table structure */ // Checked for SetInterfaceSecurityEx on IWbemServices SWORD INTFUNC ISAMOpenTable(LPISAM lpISAM, LPUSTR szTableQualifier, SWORD cbTableQualifier, LPUSTR lpszTableName, BOOL fReadOnly, LPISAMTABLEDEF FAR *lplpISAMTableDef, LPSTMT lpstmt) { HGLOBAL h; LPISAMTABLEDEF lpISAMTableDef; LPDBASEFILE lpFile; /* Opening the passthrough SQL result set? */ lpISAM->errcode = NO_ISAM_ERR; //Create a pointer to store table class definition //the class definition object will be CREATED on the HEAP //by the GetClass function or left a NULL pointer IWbemClassObject* pSingleTable = NULL; //Allocate memory for DBASEFILE h = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (DBASEFILE)); if (h == NULL || (lpFile = (LPDBASEFILE) GlobalLock (h)) == NULL) { if (h) GlobalFree(h); lpISAM->errcode = ISAM_MEMALLOCFAIL; return ISAM_MEMALLOCFAIL; } //Allocate memory for TABLEDEF h = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (ISAMTABLEDEF)); if (h == NULL || (lpISAMTableDef = (LPISAMTABLEDEF) GlobalLock (h)) == NULL) { if (h) GlobalFree(h); if (lpFile) { GlobalUnlock(GlobalPtrHandle(lpFile)); GlobalFree(GlobalPtrHandle(lpFile)); lpFile = NULL; } lpISAM->errcode = ISAM_MEMALLOCFAIL; return ISAM_MEMALLOCFAIL; } //Initialize lpFile->tempEnum = new CSafeIEnumWbemClassObject(); lpISAMTableDef->pGateway2 = new CSafeWbemServices(); lpISAMTableDef->pBStrTableName = NULL; lpISAMTableDef->pSingleTable = NULL; lpISAMTableDef->pColumnInfo = NULL; lpISAMTableDef->passthroughMap = NULL; lpISAMTableDef->firstPassthrInst = NULL; lpISAMTableDef->virtualInstances = new VirtualInstanceManager(); //Check if PassthroughSQL BOOL fIsPassthroughSQL = FALSE; char* virTbl = WBEMDR32_VIRTUAL_TABLE2; if (lpstmt && (s_lstrcmp(lpszTableName, virTbl) == 0)) { fIsPassthroughSQL = TRUE; } lpISAMTableDef->fIsPassthroughSQL = fIsPassthroughSQL; // if (s_lstrcmpi(lpszTableName, WBEMDR32_VIRTUAL_TABLE)) { //Ignore below statement /* NO, not passthough */ //First get the Gateway Interface //remember to Release it after use if (fIsPassthroughSQL) { lpISAMTableDef->pGateway2->Transfer(*(lpstmt->lpISAMStatement->pProv)); lpISAMTableDef->passthroughMap = lpstmt->lpISAMStatement->passthroughMap; lpstmt->lpISAMStatement->passthroughMap = NULL; lpISAMTableDef->firstPassthrInst= lpstmt->lpISAMStatement->firstPassthrInst; lpstmt->lpISAMStatement->firstPassthrInst = NULL; } else { lpISAMTableDef->pGateway2->SetInterfacePtr( lpISAM, szTableQualifier, cbTableQualifier); } //Check if a valid interface was returned if ( ! lpISAMTableDef->pGateway2->IsValid() ) { //Could not create a Gateway Interface, return error if (lpFile) { if (lpFile->tempEnum) { delete lpFile->tempEnum; lpFile->tempEnum = NULL; } GlobalUnlock(GlobalPtrHandle(lpFile)); GlobalFree(GlobalPtrHandle(lpFile)); lpFile = NULL; } if (lpISAMTableDef->virtualInstances) { delete (lpISAMTableDef->virtualInstances); lpISAMTableDef->virtualInstances = NULL; } if (lpISAMTableDef->pBStrTableName) { delete lpISAMTableDef->pBStrTableName; lpISAMTableDef->pBStrTableName = NULL; } if (lpISAMTableDef->pGateway2) { delete lpISAMTableDef->pGateway2; lpISAMTableDef->pGateway2 = NULL; } if (lpISAMTableDef) { GlobalUnlock(GlobalPtrHandle(lpISAMTableDef)); GlobalFree(GlobalPtrHandle(lpISAMTableDef)); lpISAMTableDef = NULL; } lpISAM->errcode = ISAM_PROVIDERFAIL; return ISAM_PROVIDERFAIL; } lpISAMTableDef->pBStrTableName = new CBString(); lpISAMTableDef->pBStrTableName->AddString((LPSTR)lpszTableName, FALSE); //Get the class definition if (fIsPassthroughSQL) { //Get class definition from lpstmt pSingleTable = lpstmt->lpISAMStatement->classDef; lpstmt->lpISAMStatement->classDef = NULL; } else { IWbemServicesPtr myServicesPtr = NULL; ISAMGetIWbemServices(lpISAM, *(lpISAMTableDef->pGateway2), myServicesPtr); if ( FAILED(myServicesPtr->GetObject(lpISAMTableDef->pBStrTableName->GetString(), 0, lpISAMTableDef->pContext, &pSingleTable, NULL)) ) { //Failed to get named class definition if (lpFile) { if (lpFile->tempEnum) { delete lpFile->tempEnum; lpFile->tempEnum = NULL; } GlobalUnlock(GlobalPtrHandle(lpFile)); GlobalFree(GlobalPtrHandle(lpFile)); lpFile = NULL; } if (lpISAMTableDef->virtualInstances) { delete (lpISAMTableDef->virtualInstances); lpISAMTableDef->virtualInstances = NULL; } if (lpISAMTableDef->pBStrTableName) { delete lpISAMTableDef->pBStrTableName; lpISAMTableDef->pBStrTableName = NULL; } if (lpISAMTableDef->pGateway2) { delete lpISAMTableDef->pGateway2; lpISAMTableDef->pGateway2 = NULL; } if (lpISAMTableDef) { GlobalUnlock(GlobalPtrHandle(lpISAMTableDef)); GlobalFree(GlobalPtrHandle(lpISAMTableDef)); lpISAMTableDef = NULL; } lpISAM->errcode = ISAM_TABLEFAIL; return ISAM_TABLEFAIL; } } } /* Fill in table definition */ lpISAMTableDef->szTableName[0] = 0; s_lstrcpy(lpISAMTableDef->szTableName, lpszTableName); s_lstrcpy(lpISAMTableDef->szPrimaryKeyName, ""); lpISAMTableDef->lpISAM = lpISAM; lpISAMTableDef->lpFile = lpFile; lpISAMTableDef->fFirstRead = TRUE; lpISAMTableDef->iRecord = -1; if (lpFile) { lpISAMTableDef->lpFile->sortArray = NULL; if (fIsPassthroughSQL) { lpISAMTableDef->lpFile->pAllRecords = new CMapWordToPtr(); lpISAMTableDef->lpFile->fMoreToCome = TRUE; //more instances need to be fetched (none fetched so far) if (lpISAMTableDef->lpFile->tempEnum) delete (lpISAMTableDef->lpFile->tempEnum); lpISAMTableDef->lpFile->tempEnum = lpstmt->lpISAMStatement->tempEnum; lpstmt->lpISAMStatement->tempEnum = NULL; //SAI NEW to avoid enumeration being deleted in ISAMFreeStatement } else { lpISAMTableDef->lpFile->pAllRecords = new CMapWordToPtr(); delete lpISAMTableDef->lpFile->tempEnum; lpISAMTableDef->lpFile->tempEnum = new CSafeIEnumWbemClassObject(); lpISAMTableDef->lpFile->fMoreToCome = FALSE; //not used but set it with a value anyway } lpISAMTableDef->lpFile->record = NULL; } lpISAMTableDef->netISAMTableDef = NET_OPAQUE_INVALID; lpISAMTableDef->hPreFetchedValues = NULL; lpISAMTableDef->cbBookmark = 0; lpISAMTableDef->bookmark.currentRecord = 0; lpISAMTableDef->bookmark.currentInstance = 0; //this is 8 - see assinment above lpISAMTableDef->pSingleTable = pSingleTable; //Contains class info //We must indicate to the class below how to parse the information //Ther unique case is when we do passthrough for multi-tables //and we get a __Generic class //We check for this BOOL fIs__Generic = FALSE; if (fIsPassthroughSQL) { //Extract class name from class definition //The table name is held in the property attribute __CLASS VARIANT grVariant; BSTR classBSTR = SysAllocString(WBEMDR32_L_CLASS); if (FAILED(pSingleTable->Get(classBSTR, 0, &grVariant, NULL, NULL))) { //SAI ADDED - Failed should we also //free pSingleTable ? lpISAM->errcode = ISAM_NOTSUPPORTED; SysFreeString(classBSTR); if (lpFile) { if (lpFile->tempEnum) { delete lpFile->tempEnum; lpFile->tempEnum = NULL; } GlobalUnlock(GlobalPtrHandle(lpFile)); GlobalFree(GlobalPtrHandle(lpFile)); lpFile = NULL; } if (lpISAMTableDef->virtualInstances) { delete (lpISAMTableDef->virtualInstances); lpISAMTableDef->virtualInstances = NULL; } if (lpISAMTableDef->pBStrTableName) { delete lpISAMTableDef->pBStrTableName; lpISAMTableDef->pBStrTableName = NULL; } if (lpISAMTableDef->pGateway2) { delete lpISAMTableDef->pGateway2; lpISAMTableDef->pGateway2 = NULL; } if (lpISAMTableDef->pSingleTable) { lpISAMTableDef->pSingleTable->Release(); lpISAMTableDef->pSingleTable = NULL; } if (lpISAMTableDef) { GlobalUnlock(GlobalPtrHandle(lpISAMTableDef)); GlobalFree(GlobalPtrHandle(lpISAMTableDef)); lpISAMTableDef = NULL; } return ISAM_NOTSUPPORTED; } SysFreeString(classBSTR); //Compare with __Generic if (_wcsicmp(grVariant.bstrVal, L"__Generic") == 0) { fIs__Generic = TRUE; } } lpISAMTableDef->fIs__Generic = fIs__Generic; ClassColumnInfoBase* tempInfo = new ClassColumnInfoBase(lpISAMTableDef,lpISAMTableDef->fIs__Generic); lpISAMTableDef->pColumnInfo = tempInfo; //DCR 29279 //Add LocaleID context object lpISAMTableDef->pContext = NULL; ISAMAddLocaleIDContextObject(lpISAMTableDef, lpISAMTableDef->lpISAM); *lplpISAMTableDef = lpISAMTableDef; return NO_ISAM_ERR; } IWbemContext* ISAMCreateLocaleIDContextObject(char* lpLocale) { IWbemContext* pContext = NULL; if (!lpLocale) return NULL; if (!lstrlen(lpLocale)) return NULL; //First get the context interface //=============================== SCODE sc = CoCreateInstance(CLSID_WbemContext, NULL, CLSCTX_INPROC_SERVER , IID_IWbemContext, (void**) ( &pContext ) ); if ( FAILED(sc) ) { ODBCTRACE("WBEM ODBC DRIVER : Failed to create context object for LocaleId"); return NULL; } //Now add the locale value _bstr_t myLocaleParm ("LocaleID"); _variant_t myLocaleVal(lpLocale); sc = pContext->SetValue(myLocaleParm, 0, &myLocaleVal); if ( FAILED(sc) ) { ODBCTRACE("WBEM ODBC DRIVER : Failed to set LocaleId in context object"); return NULL; } return pContext; } void ISAMAddLocaleIDContextObject(LPISAMTABLEDEF lpISAMTableDef, LPISAM lpISAM) { //add locale id to context object lpISAMTableDef->pContext = ISAMCreateLocaleIDContextObject(lpISAM->m_Locale); } /***************************************************************************/ SWORD INTFUNC ISAMRewind(LPISAMTABLEDEF lpISAMTableDef) { lpISAMTableDef->lpISAM->errcode = NO_ISAM_ERR; lpISAMTableDef->fFirstRead = TRUE; lpISAMTableDef->iRecord = -1; return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMSort(LPISAMTABLEDEF lpISAMTableDef, UWORD count, UWORD FAR * icol, BOOL FAR * fDescending) { if (count) { lpISAMTableDef->lpISAM->errcode = ISAM_NOTSUPPORTED; return ISAM_NOTSUPPORTED; } lpISAMTableDef->lpISAM->errcode = NO_ISAM_ERR; return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMRestrict(LPISAMTABLEDEF lpISAMTableDef, UWORD count, UWORD FAR * icol, UWORD FAR * fOperator, SWORD FAR * fCType, PTR FAR * rgbValue, SDWORD FAR * cbValue) { /* Note: Indexes are not used in this implementation, so this */ /* restriction is ignored. */ lpISAMTableDef->lpISAM->errcode = ISAM_NOTSUPPORTED; return ISAM_NOTSUPPORTED; } // Checked for SetInterfaceSecurityEx on IWbemServices void ISAMPatchUpGatewaySecurity(LPISAM lpISAM, IWbemServices* myServicesPtr) { SCODE sc = GetAuthImp( myServicesPtr, &(lpISAM->dwAuthLevel), &(lpISAM->dwImpLevel)); if(sc == S_OK) { if (lpISAM->dwAuthLevel > RPC_C_AUTHN_LEVEL_NONE) lpISAM->dwImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE; // CBString myServerStr; // myServerStr.AddString( (LPSTR)lpISAM->szServer, FALSE ); // CServerLocationCheck myCheck (myServerStr); BOOL fIsLocalConnection = lpISAM->fIsLocalConnection;//myCheck.IsLocal(); sc = ISAMSetCloaking2(myServicesPtr, fIsLocalConnection, lpISAM->fW2KOrMore, lpISAM->dwAuthLevel, lpISAM->dwImpLevel, lpISAM->gpAuthIdentity); /* if ( fIsLocalConnection && (lpISAM->fW2KOrMore) ) { sc = WbemSetDynamicCloaking(myServicesPtr, lpISAM->dwAuthLevel, lpISAM->dwImpLevel); } else { sc = SetInterfaceSecurityEx(myServicesPtr, lpISAM->gpAuthIdentity, gpPrincipal, lpISAM->dwAuthLevel, lpISAM->dwImpLevel); } */ } } /***************************************************************************/ #define WBEMDR32_ELEMENTS_TO_READ 1000 /* retrieves the next record from the selected table */ // Checked for SetInterfaceSecurityEx on IWbemServices and IEnumWbemClassObject SWORD INTFUNC ISAMNextRecord(LPISAMTABLEDEF lpISAMTableDef, LPSTMT lpstmt) { ODBCTRACE("\nWBEM ODBC Driver : ISAMNextRecord\n"); SWORD err = DBASE_ERR_SUCCESS; // Move to the next record lpISAMTableDef->lpISAM->errcode = NO_ISAM_ERR; if (lpISAMTableDef->lpFile != NULL) { if (lpISAMTableDef->fFirstRead) { //copy table name char pTableName [MAX_TABLE_NAME_LENGTH+1]; pTableName[0] = 0; wcstombs(pTableName, lpISAMTableDef->pBStrTableName->GetString(), MAX_TABLE_NAME_LENGTH); pTableName[MAX_TABLE_NAME_LENGTH] = 0; //Get enumeration of all instances of current class //First check if this table has been RESET SCODE sc; if (lpISAMTableDef->lpFile->tempEnum->IsValid()) { //Yes, reuse old enumeration //Passthrough SQL will always go here !!! sc = S_OK; } else { //no old enumeration, so create one lpISAMTableDef->lpFile->tempEnum->Invalidate(); //before getting enumeration check if we can perform //some optimization by converting to an WBEM Level 1 query //base on a single table LPSQLNODE lpRootNode = ToNode(lpstmt->lpSqlStmt, ROOT_SQLNODE); LPSQLNODE lpSqlNode2 = ToNode(lpstmt->lpSqlStmt, lpRootNode->node.root.sql); char* buffer = NULL; BOOL fOptimization = FALSE; //Check if WBEM Level 1 optimization is enabled if (lpISAMTableDef->lpISAM->fOptimization) { if ( lpSqlNode2->node.select.Predicate != NO_SQLNODE) { LPSQLNODE lpPredicateNode = ToNode(lpstmt->lpSqlStmt, lpSqlNode2->node.select.Predicate); PredicateParser theParser (&lpRootNode, lpISAMTableDef); theParser.GeneratePredicateString(lpPredicateNode, &buffer); } } //Sai Wong // if (buffer && lstrlen(buffer)) { //Get select list char* selectStr = NULL; TableColumnInfo selectInfo (&lpRootNode, &lpSqlNode2); lpISAMTableDef->passthroughMap = NULL; selectInfo.BuildSelectList(lpISAMTableDef, &selectStr, TRUE, &(lpISAMTableDef->passthroughMap)); if (selectStr) { fOptimization = TRUE; _bstr_t sqltextBSTR = L"SELECT "; _bstr_t sqltextBSTR2; sqltextBSTR += selectStr; sqltextBSTR += L" FROM "; sqltextBSTR += pTableName; //Is there a WHERE statement ? if (buffer && lstrlen(buffer)) { //RAID 29811 //If this query contains a JOIN do not add in the WHERE predicate //so we do the ON and WHERE in the correct order //Get the table list first to find out if we are //SQL-89 or SQL-92 char* checkTableList = NULL; BOOL fIsSQL89 = TRUE; selectInfo.BuildTableList(&checkTableList, fIsSQL89); delete checkTableList; if (fIsSQL89) { sqltextBSTR2 = sqltextBSTR; //make copy of this sqltextBSTR += L" WHERE "; sqltextBSTR += buffer; } } sc = lpISAMTableDef->lpFile->tempEnum->SetInterfacePtr(lpISAMTableDef->lpISAM, WMI_EXEC_QUERY, sqltextBSTR, lpISAMTableDef->pGateway2); ODBCTRACE(_T("\nWBEM ODBC Driver : Non-passthrough WQL = ")); ODBCTRACE(sqltextBSTR); ODBCTRACE(_T("\n")); CString sMessage; sMessage.Format(_T("\nWBEM ODBC Driver : sc = %ld\n"), sc); ODBCTRACE(sMessage); sMessage.Format(_T("\nWBEM ODBC Driver : LPISAM data : szUser = %s\nszPassword = %s\nszDatabase = %s\nszServer = %s\n"), lpISAMTableDef->lpISAM->szUser, lpISAMTableDef->lpISAM->szPassword, lpISAMTableDef->lpISAM->szDatabase, lpISAMTableDef->lpISAM->szServer ); ODBCTRACE(sMessage); if (! lpISAMTableDef->pGateway2->IsValid() ) ODBCTRACE( _T("\nWBEM ODBC Driver :pGateway is NULL\n")); //If ExecQuery is not supported or if there is any problems, get all entries as normal if ( (sc == WBEM_E_NOT_SUPPORTED) || (sc == WBEM_E_FAILED) || (sc == WBEM_E_INVALID_QUERY) ) { //Try it without the LIKE predicate if ( sqltextBSTR2.length() ) { if (lpISAMTableDef->lpISAM->fOptimization) { if ( lpSqlNode2->node.select.Predicate != NO_SQLNODE) { if (buffer) delete buffer; buffer = NULL; LPSQLNODE lpPredicateNode = ToNode(lpstmt->lpSqlStmt, lpSqlNode2->node.select.Predicate); PredicateParser theParser (&lpRootNode, lpISAMTableDef, FALSE); theParser.GeneratePredicateString(lpPredicateNode, &buffer); if ( buffer && lstrlen(buffer) ) { sqltextBSTR2 += L" WHERE "; sqltextBSTR2 += buffer; } ODBCTRACE(_T("\nWBEM ODBC Driver : Non-passthrough WQL (attempt 2) = ")); ODBCTRACE(sqltextBSTR2); ODBCTRACE(_T("\n")); sc = lpISAMTableDef->lpFile->tempEnum->SetInterfacePtr(lpISAMTableDef->lpISAM, WMI_EXEC_QUERY, sqltextBSTR, lpISAMTableDef->pGateway2); //If ExecQuery is not supported or if there is any problems, get all entries as normal if ( (sc == WBEM_E_NOT_SUPPORTED) || (sc == WBEM_E_FAILED) || (sc == WBEM_E_INVALID_QUERY) ) { fOptimization = FALSE; } } } } else { fOptimization = FALSE; } } delete selectStr; } } if (!fOptimization) { //no optimization allowed ODBCTRACE(_T("\nWBEM ODBC Driver : Non-passthrough WQL failed performing CreateInstanceEnum\n")); sc = lpISAMTableDef->lpFile->tempEnum->SetInterfacePtr(lpISAMTableDef->lpISAM, WMI_CREATE_INST_ENUM, lpISAMTableDef->pBStrTableName->GetString(), lpISAMTableDef->pGateway2); } //Tidy up if (buffer) delete buffer; } if ( sc != S_OK ) { err = DBASE_ERR_NODATAFOUND; } else { if (lpISAMTableDef->lpFile->tempEnum->IsValid()) { IWbemServicesPtr myServicesPtr = NULL; ISAMGetIWbemServices(lpISAMTableDef->lpISAM, *(lpISAMTableDef->pGateway2), myServicesPtr); IEnumWbemClassObjectPtr myIEnumWbemClassObject = NULL; lpISAMTableDef->lpFile->tempEnum->GetInterfacePtr(myIEnumWbemClassObject); // CBString myServerStr; // myServerStr.AddString( (LPSTR)lpISAMTableDef->lpISAM->szServer, FALSE ); // CServerLocationCheck myCheck (myServerStr); BOOL fIsLocalConnection = lpISAMTableDef->lpISAM->fIsLocalConnection;//myCheck.IsLocal(); ISAMSetCloaking2(myIEnumWbemClassObject, fIsLocalConnection, lpISAMTableDef->lpISAM->fW2KOrMore, lpISAMTableDef->lpISAM->dwAuthLevel, lpISAMTableDef->lpISAM->dwImpLevel, lpISAMTableDef->lpISAM->gpAuthIdentity); /* if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(myIEnumWbemClassObject, lpISAMTableDef->lpISAM->dwAuthLevel, lpISAMTableDef->lpISAM->dwImpLevel); } else { SetInterfaceSecurityEx(myIEnumWbemClassObject, lpISAMTableDef->lpISAM->gpAuthIdentity, gpPrincipal, lpISAMTableDef->lpISAM->dwAuthLevel, lpISAMTableDef->lpISAM->dwImpLevel); } */ //Reset to beginning of list myIEnumWbemClassObject->Reset(); //Read in ALL records (if not already read) //but only for non-passthrough SQL case //if this is passthrough SQL delay retrieval if ( (!lpISAMTableDef->fIsPassthroughSQL) && (lpISAMTableDef->lpFile->pAllRecords->IsEmpty()) ) { WORD fElements2Read = WBEMDR32_ELEMENTS_TO_READ; ULONG puReturned = 0; IWbemClassObject* myRecords [WBEMDR32_ELEMENTS_TO_READ]; //Initialize array for (ULONG loop = 0; loop < fElements2Read; loop++) { myRecords[loop] = NULL; //reset for next instance } WORD elementNumber = 0; while ( myIEnumWbemClassObject->Next(-1, fElements2Read, myRecords, &puReturned) == S_OK ) { for (loop = 0; loop < puReturned; loop++) { lpISAMTableDef->lpFile->pAllRecords->SetAt(elementNumber++, (void*)myRecords[loop] ); myRecords[loop] = NULL; //reset for next instance } puReturned = 0; } //This could be the last time around the loop if (puReturned) { for (ULONG loop = 0; loop < puReturned; loop++) { lpISAMTableDef->lpFile->pAllRecords->SetAt(elementNumber++, (void*)myRecords[loop] ); } } } //Setup bookmark lpISAMTableDef->lpFile->currentRecord = 0; } else { err = DBASE_ERR_NODATAFOUND; } } } if (err != DBASE_ERR_NODATAFOUND) { //Now fetch the next record //Check Virtual Instances //they occur if you query for array type columns which map //to multiple instances BOOL fFetchNextInstance = TRUE; if ( lpISAMTableDef->virtualInstances ) { long numInst = lpISAMTableDef->virtualInstances->cNumberOfInstances; long currInst = lpISAMTableDef->virtualInstances->currentInstance; CString myText; myText.Format("\nWBEM ODBC Driver : number of virtual instances = %ld current virtual instance = %ld\n", numInst, currInst); ODBCTRACE(myText); if ( (numInst != 0) && ( (currInst + 1) < numInst ) ) { //Don't fetch another instance //just increment virtual instance ODBCTRACE ("\nWBEM ODBC Driver : not fetching another instance, just updating virtual instance number\n"); fFetchNextInstance = FALSE; ++(lpISAMTableDef->virtualInstances->currentInstance); } } if (fFetchNextInstance) { //In passthrough SQL case you might not have any instances yet //or we might have read all the 10 instances and need to load the next batch, //therefore we make a check now if ( lpISAMTableDef->fIsPassthroughSQL ) { //Do we need to load in the next batch of 10 instances ? if ( ( lpISAMTableDef->lpFile->pAllRecords->IsEmpty() || lpISAMTableDef->lpFile->currentRecord >= BATCH_NUM_OF_INSTANCES ) && lpISAMTableDef->lpFile->fMoreToCome ) { //Yes, load next batch ODBCTRACE ("\nWBEM ODBC Driver : Need to Load next batch of 10 instances\n"); //First clear out old instances, if applicable if (! lpISAMTableDef->lpFile->pAllRecords->IsEmpty() ) { for(POSITION pos = lpISAMTableDef->lpFile->pAllRecords->GetStartPosition(); pos != NULL; ) { WORD key = 0; IWbemClassObject* pa = NULL; lpISAMTableDef->lpFile->pAllRecords->GetNextAssoc( pos, key, (void*&)pa ); if (pa) { pa->Release(); } } delete (lpISAMTableDef->lpFile->pAllRecords); lpISAMTableDef->lpFile->pAllRecords = new CMapWordToPtr(); } //Load the next 10 instances lpISAMTableDef->lpFile->currentRecord = 0; WORD fElements2Read = BATCH_NUM_OF_INSTANCES; ULONG puReturned = 0; IWbemClassObject* myRecords [BATCH_NUM_OF_INSTANCES]; //Initialize array for (ULONG loop = 0; loop < fElements2Read; loop++) { myRecords[loop] = NULL; //reset for next instance } WORD elementNumber = 0; //Special case. The 1st SQL passthrough instance was //already fetched BOOL fSpecialCase = FALSE; if (lpISAMTableDef->firstPassthrInst) { fSpecialCase = TRUE; lpISAMTableDef->lpFile->pAllRecords->SetAt(elementNumber++, (void*)lpISAMTableDef->firstPassthrInst); lpISAMTableDef->firstPassthrInst = NULL; //mark as used } ODBCTRACE("\nWBEM ODBC Driver : Calling Next(...)\n"); IEnumWbemClassObjectPtr myIEnumWbemClassObject = NULL; lpISAMTableDef->lpFile->tempEnum->GetInterfacePtr(myIEnumWbemClassObject); // Note: don't need to call SetInterfaceSecurityEx because it has already been called for this ptr // CBString myServerStr; // myServerStr.AddString( (LPSTR)lpISAMTableDef->lpISAM->szServer, FALSE ); // CServerLocationCheck myCheck (myServerStr); BOOL fIsLocalConnection = lpISAMTableDef->lpISAM->fIsLocalConnection;//myCheck.IsLocal(); if ( fIsLocalConnection && (lpISAMTableDef->lpISAM->fW2KOrMore) ) { WbemSetDynamicCloaking(myIEnumWbemClassObject, lpISAMTableDef->lpISAM->dwAuthLevel, lpISAMTableDef->lpISAM->dwImpLevel); } if (SUCCEEDED(myIEnumWbemClassObject->Next(-1, fElements2Read-(fSpecialCase?1:0), myRecords, &puReturned))) { CString myText; myText.Format("\nWBEM ODBC Driver : We got back a batch of %ld instances\n", puReturned); ODBCTRACE(myText); int i = 0; loop = 0; for (; i < puReturned; i++) { lpISAMTableDef->lpFile->pAllRecords->SetAt(elementNumber++, (void*)myRecords[i] ); loop++; } puReturned+=((fSpecialCase?1:0)); //Did we get 10 instances back or less BOOL fGotFullSetofInstances = TRUE; fGotFullSetofInstances = (puReturned == BATCH_NUM_OF_INSTANCES) ? TRUE : FALSE; if ( !fGotFullSetofInstances ) { //This is the last set of 10 instances lpISAMTableDef->lpFile->fMoreToCome = FALSE; } } } } lpISAMTableDef->lpFile->record = NULL; ODBCTRACE ("\nWBEM ODBC Driver : Fetching next instance from CMapWordToPtr\n"); BOOL fStatus = lpISAMTableDef->lpFile->pAllRecords->Lookup ((WORD)lpISAMTableDef->lpFile->currentRecord, (void* &)lpISAMTableDef->lpFile->record); //Check that a record was returned if (fStatus && lpISAMTableDef->lpFile->record) { //Increment bookmark ++(lpISAMTableDef->lpFile->currentRecord); //Remove previous virtual instance map (if there was one) delete (lpISAMTableDef->virtualInstances); lpISAMTableDef->virtualInstances = new VirtualInstanceManager(); lpISAMTableDef->virtualInstances->Load(lpISAMTableDef->passthroughMap, lpISAMTableDef->lpFile->record); } else { err = DBASE_ERR_NODATAFOUND; } } } } else { if (lpISAMTableDef->iRecord != 1) err = DBASE_ERR_SUCCESS; else err = DBASE_ERR_NODATAFOUND; } // Error if end of file? if (err == DBASE_ERR_NODATAFOUND) { lpISAMTableDef->lpISAM->errcode = ISAM_EOF; return ISAM_EOF; } else if (err != DBASE_ERR_SUCCESS) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } lpISAMTableDef->fFirstRead = FALSE; return NO_ISAM_ERR; } /***************************************************************************/ /* Provides default value for selected column */ SWORD ISAMProvideDefaultValue(SWORD fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR *pcbValue) { SWORD err = NO_ISAM_ERR; switch (fCType) { case SQL_C_DOUBLE: { //Check that you have enough buffer to store value *pcbValue = sizeof(double); if (cbValueMax >= *pcbValue) { *((double *)rgbValue) = (double)0; } else { *pcbValue = 0; err = ISAM_ERROR; } } break; case SQL_C_DATE: { *pcbValue = sizeof (DATE_STRUCT); DATE_STRUCT FAR* pDateStruct = (DATE_STRUCT FAR*)rgbValue; if ( cbValueMax >= (*pcbValue) ) { pDateStruct->year = (SWORD)0; pDateStruct->month = (UWORD)0; pDateStruct->day = (UWORD)0; } else { *pcbValue = 0; err = ISAM_ERROR; } } break; case SQL_C_TIME: { //Check that you have enough buffer to store value *pcbValue = sizeof (TIME_STRUCT); TIME_STRUCT FAR* pTimeStruct = (TIME_STRUCT FAR*)rgbValue; if ( cbValueMax >= (*pcbValue) ) { pTimeStruct->hour = (UWORD)0; pTimeStruct->minute = (UWORD)0; pTimeStruct->second = (UWORD)0; } else { *pcbValue = 0; err = ISAM_ERROR; } } break; case SQL_C_TIMESTAMP: { //Check that you have enough buffer to store value *pcbValue = sizeof (TIMESTAMP_STRUCT); TIMESTAMP_STRUCT FAR* pTimeStampStruct = (TIMESTAMP_STRUCT FAR*)rgbValue; if ( cbValueMax >= (*pcbValue) ) { pTimeStampStruct->year = (SWORD)0; pTimeStampStruct->month = (UWORD)0; pTimeStampStruct->day = (UWORD)0; pTimeStampStruct->hour = (UWORD)0; pTimeStampStruct->minute = (UWORD)0; pTimeStampStruct->second = (UWORD)0; pTimeStampStruct->fraction = 0; } else { *pcbValue = 0; err = ISAM_ERROR; } } break; case SQL_C_CHAR: case SQL_C_BINARY: default: { *pcbValue = SQL_NULL_DATA; } break; } return err; } /***************************************************************************/ /* Gets the data value for the selected column */ SWORD INTFUNC ISAMGetData(LPISAMTABLEDEF lpISAMTableDef, UWORD icol, SDWORD cbOffset, SWORD fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR *pcbValue) { //This manages the thread locale id ThreadLocaleIdManager myThreadStuff(lpISAMTableDef->lpISAM); lpISAMTableDef->lpISAM->errcode = NO_ISAM_ERR; if ((fCType != SQL_CHAR) && (lpISAMTableDef->lpFile == NULL)) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; ODBCTRACE("\nWBEM ODBC Driver : ISAMGetData : Error position 1\n"); return ISAM_ERROR; } if (cbValueMax == SQL_NTS) cbValueMax = s_lstrlen (rgbValue); //create SAFEARRAY to store BSTR's SAFEARRAY FAR* rgSafeArray = NULL; //Create a store for column name BSTR lpbString; CBString temppbString; //Stores table alias CBString cbTableAlias; //Check if you have a __Generic class BOOL fIs__Generic = lpISAMTableDef->fIs__Generic; //Points to the current instance for the property IWbemClassObjectPtr theRecord = NULL; //Points to the current class definition IWbemClassObjectPtr theClassDefinition = NULL; if (!fIs__Generic) { //Setup the record pointer theRecord = lpISAMTableDef->lpFile->record; //Setup the class definition pointer theClassDefinition = lpISAMTableDef->pSingleTable; //Fetch name of column "icol" //Remeber with abstract and derived classes the properities in the class definition //may be different to the properties in the instances. //The "icol" maps to a class property,so we get the names from the class lpISAMTableDef->pSingleTable->GetNames(NULL, 0, NULL, &rgSafeArray); SafeArrayLock(rgSafeArray); LONG iColumnNum = (LONG)icol; if ( FAILED(SafeArrayGetElement(rgSafeArray, &iColumnNum, &lpbString)) ) { //To be more resilient we specify a default value //NULL for SQL_C_CHAR and zero for numeric values SWORD fErr = ISAMProvideDefaultValue(fCType, rgbValue, cbValueMax, pcbValue); if (fErr != NO_ISAM_ERR) { lpISAMTableDef->lpISAM->errcode = fErr; SafeArrayUnlock(rgSafeArray); SafeArrayDestroy(rgSafeArray); //SAI ADDED ODBCTRACE("\nWBEM ODBC Driver : ISAMGetData : Error position 2\n"); return fErr; } SafeArrayUnlock(rgSafeArray); SafeArrayDestroy(rgSafeArray); //SAI ADDED return NO_ISAM_ERR; } #ifdef TESTING //copy column name char pColumnName [MAX_COLUMN_NAME_LENGTH+1]; pColumnName[0] = 0; wcstombs(pColumnName, lpbString, MAX_COLUMN_NAME_LENGTH); pColumnName[MAX_COLUMN_NAME_LENGTH] = 0; #endif } else { //Get the icol from passthrough map PassthroughLookupTable* passthroughElement = NULL; WORD myIndex = (WORD)icol; BOOL status = lpISAMTableDef->passthroughMap->Lookup(myIndex, (void*&)passthroughElement); if (status) { temppbString.AddString(passthroughElement->GetColumnName(), FALSE); char* lpTableAlias = passthroughElement->GetTableAlias(); cbTableAlias.AddString(lpTableAlias, FALSE); //Get the embedded object (keyed on table alias) VARIANT vEmbedded; if ( SUCCEEDED(lpISAMTableDef->lpFile->record->Get(cbTableAlias.GetString(), 0, &vEmbedded, NULL, NULL)) ) { IUnknown* myUnk = vEmbedded.punkVal; myUnk->QueryInterface(IID_IWbemClassObject, (void**)&theRecord); VariantClear(&vEmbedded); } else { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; ODBCTRACE("\nWBEM ODBC Driver : ISAMGetData : Error position 3\n"); return ISAM_ERROR; } //Do the same for class definition VARIANT vClassEmbedded; if ( SUCCEEDED(lpISAMTableDef->lpFile->record->Get(cbTableAlias.GetString(), 0, &vClassEmbedded, NULL, NULL)) ) { IUnknown* myUnk = vClassEmbedded.punkVal; myUnk->QueryInterface(IID_IWbemClassObject, (void**)&theClassDefinition); VariantClear(&vClassEmbedded); } else { //(9) Should we release theRecord lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; ODBCTRACE("\nWBEM ODBC Driver : ISAMGetData : Error position 4\n"); return ISAM_ERROR; } } else { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; ODBCTRACE("\nWBEM ODBC Driver : ISAMGetData : Error position 5\n"); return ISAM_ERROR; } } //Get the value of the column CIMTYPE wbemType = 0; SWORD wbemVariantType = 0; VARIANT vVariantVal; if ( FAILED(theRecord->Get(fIs__Generic ? temppbString.GetString() : lpbString, 0, &vVariantVal, &wbemType, NULL)) ) { //To be more resilient we specify a default value //NULL for SQL_C_CHAR and zero for numeric values SWORD fErr = ISAMProvideDefaultValue(fCType, rgbValue, cbValueMax, pcbValue); //Tidy up if (rgSafeArray) { SafeArrayUnlock(rgSafeArray); SafeArrayDestroy(rgSafeArray); } if (fErr != NO_ISAM_ERR) { //(9) Should we release theRecord and theClassDefinition //if __generic ? lpISAMTableDef->lpISAM->errcode = fErr; if (!fIs__Generic) SysFreeString(lpbString); ODBCTRACE("\nWBEM ODBC Driver : ISAMGetData : Error position 6\n"); return fErr; } //(9) Should we release theRecord and theClassDefinition //if __generic ? if (!fIs__Generic) SysFreeString(lpbString); return NO_ISAM_ERR; } //New //Get attributes for chosen column IWbemQualifierSetPtr pQualifierSet = NULL; if ( S_OK != (theClassDefinition->GetPropertyQualifierSet(fIs__Generic ? temppbString.GetString() : lpbString, &pQualifierSet)) ) { pQualifierSet = NULL; } //Tidy up if (rgSafeArray) { SafeArrayUnlock(rgSafeArray); SafeArrayDestroy(rgSafeArray); } //Get CIMTYPE String VARIANT pVal2; BSTR syntaxStr = NULL; BOOL fClearpVal2 = FALSE; if (pQualifierSet) { BSTR cimtypeBSTR = SysAllocString(WBEMDR32_L_CIMTYPE); SCODE result = pQualifierSet->Get(cimtypeBSTR, 0, &pVal2, 0); SysFreeString(cimtypeBSTR); if ( S_OK == result ) { if (pVal2.bstrVal) syntaxStr = pVal2.bstrVal; fClearpVal2 = TRUE; } } //Get MAXLEN Value VARIANT pVal3; SDWORD maxLenVal = 0; if (pQualifierSet) { BSTR maxBSTR = SysAllocString(WBEMDR32_L_MAX); SCODE result = pQualifierSet->Get(maxBSTR, 0, &pVal3, 0); SysFreeString(maxBSTR); if ( S_OK == result ) { maxLenVal = pVal3.iVal; VariantClear(&pVal3); } } //Get value from variant ISAMGetWbemVariantType(wbemType, wbemVariantType); //get the index for this column long index = -1; _bstr_t theTableAlias = cbTableAlias.GetString(); _bstr_t theColumnName = fIs__Generic ? temppbString.GetString() : lpbString; if (lpISAMTableDef->virtualInstances) { long theInstance = lpISAMTableDef->virtualInstances->currentInstance; //Remove previous virtual instance map (if there was one) delete (lpISAMTableDef->virtualInstances); lpISAMTableDef->virtualInstances = new VirtualInstanceManager(); lpISAMTableDef->virtualInstances->Load(lpISAMTableDef->passthroughMap, lpISAMTableDef->lpFile->record); //Restore current instance lpISAMTableDef->virtualInstances->currentInstance = theInstance; index = lpISAMTableDef->virtualInstances->GetArrayIndex(theTableAlias, theColumnName, theInstance); } if (!fIs__Generic) SysFreeString(lpbString); SWORD err = ISAMGetValueFromVariant(vVariantVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal, index); if (fClearpVal2) VariantClear(&pVal2); if (err != NO_ISAM_ERR) { lpISAMTableDef->lpISAM->errcode = err; ODBCTRACE("\nWBEM ODBC Driver : ISAMGetData : Error position 7\n"); return err; } VariantClear(&vVariantVal); return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMPutData(LPISAMTABLEDEF lpISAMTableDef, UWORD icol, SWORD fCType, PTR rgbValue, SDWORD cbValue) { /* Not allowed for the passthrough table */ lpISAMTableDef->lpISAM->errcode = NO_ISAM_ERR; if (lpISAMTableDef->lpFile == NULL) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } /* Null? */ if (cbValue == SQL_NULL_DATA) { /* Yes. Set value to NULL */ if (dBaseSetColumnNull(lpISAMTableDef->lpFile, (UWORD) (icol+1)) != DBASE_ERR_SUCCESS) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } } else { /* No. Set the value */ switch (fCType) { case SQL_C_DOUBLE: { UCHAR string[20]; if (DoubleToChar(*((double far *)rgbValue), TRUE, (LPUSTR)string, sizeof(string))) string[sizeof(string)-1] = '\0'; if (dBaseSetColumnCharVal(lpISAMTableDef->lpFile, (UWORD) (icol+1), string, lstrlen((char*)string)) != DBASE_ERR_SUCCESS) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } } break; case SQL_C_CHAR: if (cbValue == SQL_NTS) cbValue = lstrlen((char*)rgbValue); if (dBaseSetColumnCharVal(lpISAMTableDef->lpFile, (UWORD) (icol+1), (UCHAR FAR*)rgbValue, cbValue) != DBASE_ERR_SUCCESS) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } break; case SQL_C_DATE: { UCHAR string[11]; DateToChar((DATE_STRUCT far *) rgbValue, (LPUSTR)string); if (dBaseSetColumnCharVal(lpISAMTableDef->lpFile, (UWORD) (icol+1), string, lstrlen((char*)string)) != DBASE_ERR_SUCCESS) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } } break; default: lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } } return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMInsertRecord(LPISAMTABLEDEF lpISAMTableDef) { lpISAMTableDef->lpISAM->errcode = NO_ISAM_ERR; if (lpISAMTableDef->lpFile == NULL) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } if (dBaseAddRecord(lpISAMTableDef->lpFile) != DBASE_ERR_SUCCESS) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMUpdateRecord(LPISAMTABLEDEF lpISAMTableDef) { lpISAMTableDef->lpISAM->errcode = NO_ISAM_ERR; if (lpISAMTableDef->lpFile == NULL) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMDeleteRecord(LPISAMTABLEDEF lpISAMTableDef) { lpISAMTableDef->lpISAM->errcode = NO_ISAM_ERR; if (lpISAMTableDef->lpFile == NULL) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } if (dBaseDeleteRecord(lpISAMTableDef->lpFile) != DBASE_ERR_SUCCESS) { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMGetBookmark(LPISAMTABLEDEF lpISAMTableDef, LPISAMBOOKMARK lpISAMBookmark) { lpISAMTableDef->lpISAM->errcode = NO_ISAM_ERR; if (lpISAMTableDef->lpFile != NULL) { lpISAMBookmark->currentRecord = lpISAMTableDef->lpFile->currentRecord; } else { lpISAMBookmark->currentRecord = lpISAMTableDef->iRecord; } if (lpISAMTableDef->virtualInstances) { lpISAMBookmark->currentInstance = lpISAMTableDef->virtualInstances->currentInstance; } return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMPosition(LPISAMTABLEDEF lpISAMTableDef, LPISAMBOOKMARK ISAMBookmark) { lpISAMTableDef->lpISAM->errcode = NO_ISAM_ERR; if ( lpISAMTableDef->lpFile && lpISAMTableDef->lpFile->tempEnum->IsValid()) { BOOL fStatus = lpISAMTableDef->lpFile->pAllRecords->Lookup ( (WORD)(ISAMBookmark->currentRecord - 1), (void* &)lpISAMTableDef->lpFile->record); if (fStatus && lpISAMTableDef->lpFile->record) { //Update bookmark to next entry lpISAMTableDef->lpFile->currentRecord = ISAMBookmark->currentRecord;// + 1; } else { lpISAMTableDef->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } } else { lpISAMTableDef->iRecord = (SDWORD) ISAMBookmark->currentRecord; } if (lpISAMTableDef->virtualInstances) { lpISAMTableDef->virtualInstances->currentInstance = ISAMBookmark->currentInstance; } return NO_ISAM_ERR; } /***************************************************************************/ /* Closes a specific table and deallocates the table definition */ SWORD INTFUNC ISAMCloseTable(LPISAMTABLEDEF lpISAMTableDef) { //Check if lpISAMTableDef exists if (! lpISAMTableDef) return NO_ISAM_ERR; /* Close the dBASE file */ lpISAMTableDef->lpISAM->errcode = NO_ISAM_ERR; if (lpISAMTableDef->lpFile != NULL) { //Release interface pointers if applicable //Empty out all instances if (lpISAMTableDef->lpFile->pAllRecords) { for(POSITION pos = lpISAMTableDef->lpFile->pAllRecords->GetStartPosition(); pos != NULL; ) { WORD key = 0; IWbemClassObject* pa = NULL; lpISAMTableDef->lpFile->pAllRecords->GetNextAssoc( pos, key, (void*&)pa ); if (pa) { pa->Release(); } } delete (lpISAMTableDef->lpFile->pAllRecords); lpISAMTableDef->lpFile->pAllRecords = NULL; } if (lpISAMTableDef->lpFile->tempEnum) { delete (lpISAMTableDef->lpFile->tempEnum); lpISAMTableDef->lpFile->tempEnum = NULL; } } if (lpISAMTableDef->pBStrTableName) { delete (lpISAMTableDef->pBStrTableName); lpISAMTableDef->pBStrTableName = NULL; } if (lpISAMTableDef->pSingleTable) { lpISAMTableDef->pSingleTable->Release(); lpISAMTableDef->pSingleTable = NULL; } TidyupPassthroughMap(lpISAMTableDef->passthroughMap); lpISAMTableDef->passthroughMap = NULL; if (lpISAMTableDef->pGateway2) { delete lpISAMTableDef->pGateway2; lpISAMTableDef->pGateway2 = NULL; } if (lpISAMTableDef->pColumnInfo) { delete (lpISAMTableDef->pColumnInfo); lpISAMTableDef->pColumnInfo = NULL; } if (lpISAMTableDef->pContext) { lpISAMTableDef->pContext->Release(); lpISAMTableDef->pContext = NULL; } if (lpISAMTableDef->lpFile) { GlobalUnlock(GlobalPtrHandle(lpISAMTableDef->lpFile)); GlobalFree(GlobalPtrHandle(lpISAMTableDef->lpFile)); lpISAMTableDef->lpFile = NULL; } delete lpISAMTableDef->virtualInstances; lpISAMTableDef->virtualInstances = NULL; GlobalUnlock(GlobalPtrHandle(lpISAMTableDef)); GlobalFree(GlobalPtrHandle(lpISAMTableDef)); lpISAMTableDef = NULL; return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMDeleteTable(LPISAM lpISAM, LPUSTR lpszTableName) { return ISAM_NOTSUPPORTED; /* UCHAR szFilename[MAX_DATABASE_NAME_LENGTH+MAX_TABLE_NAME_LENGTH+6]; // Create the filename lpISAM->errcode = NO_ISAM_ERR; lstrcpy((char*)szFilename, (char*)lpISAM->szDatabase); lstrcat((char*)szFilename, "\\"); lstrcat((char*)szFilename, lpszTableName); lstrcat((char*)szFilename, ".DBF"); // Delete the file dBaseDestroy((char*)szFilename); return NO_ISAM_ERR; */ } /***************************************************************************/ // Checked for SetInterfaceSecurityEx on IWbemServices and IEnumWbemClassObject SWORD INTFUNC ISAMPrepare(LPISAM lpISAM, UCHAR FAR *szSqlStr, SDWORD cbSqlStr, LPISAMSTATEMENT FAR *lplpISAMStatement, LPUSTR lpszTablename, UWORD FAR *lpParameterCount #ifdef IMPLTMT_PASSTHROUGH , LPSTMT lpstmt #endif ) { ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare\n")); //For now disable Passthrough SQL // lpISAM->errcode = ISAM_NOTSUPPORTED; // return ISAM_NOTSUPPORTED; /* //Test CBString s1; CBString s2; CBString s3; CBString s4; CBString s5; s1.AddString("", FALSE); s2.AddString(NULL, FALSE); s3.AddString("\\\\.", FALSE); s4.AddString("\\\\SaiWong4", FALSE); s5.AddString("\\\\SaiWong2", FALSE); CServerLocationCheck one(s1); CServerLocationCheck two(s2); CServerLocationCheck three(s3); CServerLocationCheck four(s4); CServerLocationCheck five(s5); */ HGLOBAL h; LPISAMSTATEMENT lpISAMStatement; lpISAM->errcode = NO_ISAM_ERR; h = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof (ISAMSTATEMENT)); if (h == NULL || (lpISAMStatement = (LPISAMSTATEMENT) GlobalLock (h)) == NULL) { if (h) GlobalFree(h); lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 1\n")); //Initialize passthrough parameters lpISAMStatement->pProv = NULL; lpISAMStatement->currentRecord = 0; lpISAMStatement->tempEnum = new CSafeIEnumWbemClassObject(); lpISAMStatement->firstPassthrInst = NULL; lpISAMStatement->classDef = NULL; lpISAMStatement->tempEnum2 = new CSafeIEnumWbemClassObject(); if ((cbSqlStr == 15) && (!_fmemicmp(szSqlStr, "MessageBox(?,?)", 15))) { s_lstrcpy(lpszTablename, ""); *lpParameterCount = 2; lpISAMStatement->lpISAM = lpISAM; lpISAMStatement->resultSet = FALSE; lpISAMStatement->lpszParam1 = NULL; lpISAMStatement->cbParam1 = SQL_NULL_DATA; lpISAMStatement->lpszParam2 = NULL; lpISAMStatement->cbParam2 = SQL_NULL_DATA; } #ifdef IMPLTMT_PASSTHROUGH else if (TRUE) { //Try passthrough *lpParameterCount = 0; lpISAMStatement->lpISAM = lpISAM; lpISAMStatement->resultSet = TRUE; lpISAMStatement->lpszParam1 = NULL; lpISAMStatement->cbParam1 = SQL_NULL_DATA; lpISAMStatement->lpszParam2 = NULL; lpISAMStatement->cbParam2 = SQL_NULL_DATA; ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 2\n")); /* No. Create a PASSTHROUGH parse tree */ SCODE sc = Parse(lpstmt, lpISAM, (LPUSTR) szSqlStr, cbSqlStr, &(lpstmt->lpSqlStmt)); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 3\n")); if (sc != SQL_SUCCESS) { FreeTree(lpstmt->lpSqlStmt); lpstmt->lpSqlStmt = NULL; delete lpISAMStatement->tempEnum; delete lpISAMStatement->tempEnum2; GlobalUnlock(h); GlobalFree(h); lpISAM->errcode = ISAM_NOTSUPPORTED; return ISAM_NOTSUPPORTED; } //Need to do a semantic check so that any //Table.* will get expanded sc = SemanticCheck(lpstmt, &(lpstmt->lpSqlStmt), ROOT_SQLNODE, FALSE, ISAMCaseSensitive(lpstmt->lpdbc->lpISAM), NO_SQLNODE, NO_SQLNODE); if (sc != SQL_SUCCESS) { FreeTree(lpstmt->lpSqlStmt); lpstmt->lpSqlStmt = NULL; delete lpISAMStatement->tempEnum; delete lpISAMStatement->tempEnum2; GlobalUnlock(h); GlobalFree(h); lpISAM->errcode = ISAM_NOTSUPPORTED; return ISAM_NOTSUPPORTED; } ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 3b\n")); //Generate WQL statement using parse tree LPSQLNODE lpRootNode = ToNode(lpstmt->lpSqlStmt, ROOT_SQLNODE); LPSQLNODE lpSqlNode2 = ToNode(lpstmt->lpSqlStmt, lpRootNode->node.root.sql); char* fullWQL = NULL; BOOL fHasAggregateFunctions = FALSE; TableColumnInfo selectInfo (&lpRootNode, &lpSqlNode2, WQL_MULTI_TABLE); CMapWordToPtr* passthroughMap; selectInfo.BuildFullWQL(&fullWQL, &passthroughMap); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 3c\n")); //Extra check for aggregate functions what WQL does not support //so we must fail SQL passthrough if ( selectInfo.HasAggregateFunctions() ) { fHasAggregateFunctions = TRUE; } //At this point we can check for 'SELECT * FROM .....' //If this is so we need to work out the full column list //and re-parse and try again (only for single tables) if ( selectInfo.IsSelectStar() && selectInfo.IsZeroOrOneList() ) { //get new query string char* lpWQLStr = NULL; char* lpWQLSelectStarList = NULL; BOOL fIsThisDistinct = selectInfo.IsDistinct(); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 4\n")); ISAMGetSelectStarList(&lpWQLSelectStarList, &selectInfo, lpISAM); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 5\n")); //clean up parse tree FreeTree(lpstmt->lpSqlStmt); lpstmt->lpSqlStmt = NULL; //clean up passthrough map TidyupPassthroughMap(passthroughMap); passthroughMap = NULL; ISAMStringConcat(&lpWQLStr, "SELECT "); //Add tail end of previous string char* oldString = fullWQL; oldString += 7; //skip over SELECT if ( fIsThisDistinct ) { ISAMStringConcat(&lpWQLStr, "distinct "); oldString += 9; //skip over DISTINCT } if (lpWQLSelectStarList) { ISAMStringConcat(&lpWQLStr, lpWQLSelectStarList); } ISAMStringConcat(&lpWQLStr, oldString); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 6\n")); CString sMessage; sMessage.Format("\nWBEM ODBC Driver : detected select * : reparsing query :\n%s\n", lpWQLStr); ODBCTRACE(sMessage); // No. Create a PASSTHROUGH parse tree sc = Parse(lpstmt, lpISAM, (LPUSTR) lpWQLStr, lstrlen(lpWQLStr), &(lpstmt->lpSqlStmt)); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 7\n")); if (lpWQLStr) delete lpWQLStr; if (sc != SQL_SUCCESS) { FreeTree(lpstmt->lpSqlStmt); lpstmt->lpSqlStmt = NULL; delete lpISAMStatement->tempEnum; delete lpISAMStatement->tempEnum2; GlobalUnlock(h); GlobalFree(h); lpISAM->errcode = ISAM_NOTSUPPORTED; return ISAM_NOTSUPPORTED; } //Generate WQL statement using parse tree lpRootNode = ToNode(lpstmt->lpSqlStmt, ROOT_SQLNODE); lpSqlNode2 = ToNode(lpstmt->lpSqlStmt, lpRootNode->node.root.sql); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 8\n")); delete fullWQL; fullWQL = NULL; TableColumnInfo selectInfo2 (&lpRootNode, &lpSqlNode2, WQL_MULTI_TABLE); selectInfo2.BuildFullWQL(&fullWQL, &passthroughMap); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 9\n")); //Extra check for aggregate functions what WQL does not support //so we must fail SQL passthrough if ( selectInfo2.HasAggregateFunctions() ) { fHasAggregateFunctions = TRUE; } } _bstr_t sqltextBSTR = fullWQL; delete fullWQL; CString wqlTextDebug(_T("\nWBEM ODBC Driver : WQL query : ")); wqlTextDebug += (LPCTSTR)sqltextBSTR; wqlTextDebug += _T("\n"); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 7b\n")); //Get instances by executing query sc = WBEM_E_FAILED; char* lpTblQualifier = NULL; // if (idxQual != NO_STRING) // { // lpTblQualifier = (LPSTR) ToString(lpRootNode, idxQual); // } // else { lpTblQualifier = lpstmt->lpdbc->lpISAM->szDatabase; } ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 7c\n")); lpISAMStatement->pProv = new CSafeWbemServices(); lpISAMStatement->pProv->SetInterfacePtr(lpstmt->lpdbc->lpISAM, (LPUSTR) lpTblQualifier, (SWORD) lstrlen(lpTblQualifier)); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 7d\n")); lpISAMStatement->passthroughMap = passthroughMap; //Get prototype 'class' definition if (lpISAMStatement->pProv->IsValid()) { ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 10\n")); sc = lpISAMStatement->tempEnum2->SetInterfacePtr(lpstmt->lpdbc->lpISAM, WMI_PROTOTYPE, sqltextBSTR, lpISAMStatement->pProv); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 11\n")); //Extra check for aggregate functions what WQL does not support //so we must fail SQL passthrough if ( fHasAggregateFunctions ) { sc = WBEM_E_NOT_SUPPORTED; } } else { sc = WBEM_E_NOT_SUPPORTED; ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 7e\n")); } if ( (sc == WBEM_E_NOT_SUPPORTED) || (sc == WBEM_E_FAILED) || (sc == WBEM_E_INVALID_QUERY) || (sc == WBEM_E_NOT_FOUND) || (sc == WBEM_E_ACCESS_DENIED) ) { if ( fHasAggregateFunctions ) { ODBCTRACE(_T("\nWBEM ODBC Driver : Failing SQL passthrough as original SQL query has aggregate functions which WQL does not support\n")); } else { ODBCTRACE(_T("\nWBEM ODBC Driver : Getting prototype failed\n")); } //ExecQuery failed delete lpISAMStatement->pProv; lpISAMStatement->pProv = NULL; TidyupPassthroughMap(lpISAMStatement->passthroughMap); lpISAMStatement->passthroughMap = NULL; FreeTree(lpstmt->lpSqlStmt); lpstmt->lpSqlStmt = NULL; ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 12\n")); delete lpISAMStatement->tempEnum; delete lpISAMStatement->tempEnum2; GlobalUnlock(h); GlobalFree(h); lpISAM->errcode = ISAM_NOTSUPPORTED; return ISAM_NOTSUPPORTED; } ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 12\n")); IWbemServicesPtr myServicesPtr = NULL; ISAMGetIWbemServices(lpISAM, *(lpISAMStatement->pProv), myServicesPtr); IEnumWbemClassObjectPtr myIEnumWbemClassObject = NULL; lpISAMStatement->tempEnum2->GetInterfacePtr(myIEnumWbemClassObject); // CBString myServerStr; // myServerStr.AddString( (LPSTR)lpISAM->szServer, FALSE ); // CServerLocationCheck myCheck (myServerStr); BOOL fIsLocalConnection = lpISAM->fIsLocalConnection;//myCheck.IsLocal(); ISAMSetCloaking2(myIEnumWbemClassObject, fIsLocalConnection, lpISAM->fW2KOrMore, lpISAM->dwAuthLevel, lpISAM->dwImpLevel, lpISAM->gpAuthIdentity); /* if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(myIEnumWbemClassObject, lpISAM->dwAuthLevel, lpISAM->dwImpLevel); } else { SetInterfaceSecurityEx(myIEnumWbemClassObject, lpISAM->gpAuthIdentity, gpPrincipal, lpISAM->dwAuthLevel, lpISAM->dwImpLevel); } */ ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 13\n")); //There should be only 1 instance which is the class definition ULONG puReturned = 0; ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 14\n")); myIEnumWbemClassObject->Reset(); if (myIEnumWbemClassObject->Next(-1, 1, &(lpISAMStatement->classDef), &puReturned) != S_OK) { ODBCTRACE(_T("\nWBEM ODBC Driver : Getting Prototype instance failed\n")); delete lpISAMStatement->pProv; lpISAMStatement->pProv = NULL; TidyupPassthroughMap(lpISAMStatement->passthroughMap); lpISAMStatement->passthroughMap = NULL; FreeTree(lpstmt->lpSqlStmt); lpstmt->lpSqlStmt = NULL; delete lpISAMStatement->tempEnum; delete lpISAMStatement->tempEnum2; GlobalUnlock(h); GlobalFree(h); lpISAM->errcode = ISAM_NOTSUPPORTED; return ISAM_NOTSUPPORTED; } //Now execute the real query if (lpISAMStatement->pProv->IsValid()) { sc = lpISAMStatement->tempEnum->SetInterfacePtr(lpISAM, WMI_EXEC_FWD_ONLY, sqltextBSTR, lpISAMStatement->pProv); ODBCTRACE(_T("\nWBEM ODBC Driver :ISAMPrepare : Pos 15\n")); //As semi-synchronous does not indicate if any error occurs //we need to get the first record back now if ( SUCCEEDED(sc) ) { IEnumWbemClassObjectPtr myIEnumWbemClassObj1 = NULL; lpISAMStatement->tempEnum->GetInterfacePtr(myIEnumWbemClassObj1); ISAMSetCloaking2(myIEnumWbemClassObj1, fIsLocalConnection, lpISAM->fW2KOrMore, lpISAM->dwAuthLevel, lpISAM->dwImpLevel, lpISAM->gpAuthIdentity); /* if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(myIEnumWbemClassObj1, lpISAM->dwAuthLevel, lpISAM->dwImpLevel); } else { SetInterfaceSecurityEx(myIEnumWbemClassObj1, lpISAM->gpAuthIdentity, gpPrincipal, lpISAM->dwAuthLevel, lpISAM->dwImpLevel); } */ ULONG numReturned = 0; sc = myIEnumWbemClassObj1->Next(-1, 1, &(lpISAMStatement->firstPassthrInst), &numReturned); } } else { sc = WBEM_E_NOT_SUPPORTED; } CString sSCODE; sSCODE.Format("\nMAGIC NUMBER = 0x%X\n", sc); ODBCTRACE(sSCODE); if ( sc != WBEM_S_NO_ERROR ) { ODBCTRACE(_T("\nWBEM ODBC Driver : Passthrough SQL Failed or Not Supported\n")); //ExecQuery failed lpISAM->errcode = ERR_PASSTGHONLY_NOTSUPP; //default error string ((char*)lpstmt->szISAMError)[0] = 0; CString sDefaultError; sDefaultError.LoadString(STR_EXECQUERY); sprintf((char*)lpstmt->szError, "%s 0x%X", sDefaultError, sc); lpISAM->errcode = ERR_WBEM_SPECIFIC; //Test here //need to get the WBEM specific error IErrorInfo* pEI = NULL; IWbemClassObject *pErrorObject = NULL; if(GetErrorInfo(0, &pEI) == S_OK) { pEI->QueryInterface(IID_IWbemClassObject, (void**)&pErrorObject); pEI->Release(); } if (pErrorObject) { VARIANT varString; if (pErrorObject->InheritsFrom(L"__NotifyStatus") != WBEM_NO_ERROR) { // fprintf(stdout, "Unrecognized Error Object type\n"); } else if (pErrorObject->InheritsFrom(L"__ExtendedStatus") == WBEM_NO_ERROR) { sc = pErrorObject->Get(L"Description", 0L, &varString, NULL, NULL); if ( (sc == S_OK) && (varString.vt == VT_BSTR) ) { lstrcpy((char*)lpstmt->szISAMError, ""); wcstombs((char*)lpstmt->szError,varString.bstrVal ? varString.bstrVal : L" ", MAX_ERROR_LENGTH); lpISAM->errcode = ERR_WBEM_SPECIFIC; VariantClear(&varString); } } pErrorObject->Release(); } delete lpISAMStatement->pProv; lpISAMStatement->pProv = NULL; lpISAMStatement->classDef->Release(); TidyupPassthroughMap(lpISAMStatement->passthroughMap); lpISAMStatement->passthroughMap = NULL; SWORD savedErrorCode = lpISAM->errcode; FreeTree(lpstmt->lpSqlStmt); lpstmt->lpSqlStmt = NULL; delete lpISAMStatement->tempEnum; delete lpISAMStatement->tempEnum2; GlobalUnlock(h); GlobalFree(h); lpISAM->errcode = savedErrorCode; return ISAM_NOTSUPPORTED; } //ExecQuery succeeded myServicesPtr = NULL; ISAMGetIWbemServices(lpISAM, *(lpISAMStatement->pProv), myServicesPtr); //free up enumeration before resetting to NULL IEnumWbemClassObject* tempEnum = myIEnumWbemClassObject.Detach(); if (tempEnum) tempEnum->Release(); myIEnumWbemClassObject = NULL; lpISAMStatement->tempEnum->GetInterfacePtr(myIEnumWbemClassObject); ISAMSetCloaking2(myIEnumWbemClassObject, fIsLocalConnection, lpISAM->fW2KOrMore, lpISAM->dwAuthLevel, lpISAM->dwImpLevel, lpISAM->gpAuthIdentity); /* if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(myIEnumWbemClassObject, lpISAM->dwAuthLevel, lpISAM->dwImpLevel); } else { SetInterfaceSecurityEx(myIEnumWbemClassObject, lpISAM->gpAuthIdentity, gpPrincipal, lpISAM->dwAuthLevel, lpISAM->dwImpLevel); } */ ODBCTRACE(_T("\nWBEM ODBC Driver : Passthrough SQL succeeded, getting instances\n")); //Copy table name lpszTablename[0] = 0; wchar_t* virTbl = WBEMDR32_VIRTUAL_TABLE; wcstombs((char*)lpszTablename, virTbl, MAX_TABLE_NAME_LENGTH); lpszTablename[MAX_TABLE_NAME_LENGTH] = 0; //Free the Parse tree. //A new Parse tree will be created for //SELECT * FROM WBEMDR32VirtualTable FreeTree(lpstmt->lpSqlStmt); lpstmt->lpSqlStmt = NULL; } #else else if ((cbSqlStr == 3) && (!_fmemicmp(szSqlStr, "SQL", 3))) { s_lstrcpy(lpszTablename, "SQL"); *lpParameterCount = 0; lpISAMStatement->lpISAM = lpISAM; lpISAMStatement->resultSet = TRUE; lpISAMStatement->lpszParam1 = NULL; lpISAMStatement->cbParam1 = SQL_NULL_DATA; lpISAMStatement->lpszParam2 = NULL; lpISAMStatement->cbParam2 = SQL_NULL_DATA; } else { test if we reach here delete lpISAMStatement->tempEnum; delete lpISAMStatement->tempEnum2; GlobalUnlock(h); GlobalFree(h); lpISAM->errcode = ISAM_NOTSUPPORTED; return ISAM_NOTSUPPORTED; } #endif *lplpISAMStatement = lpISAMStatement; return NO_ISAM_ERR; } // Checked for SetInterfaceSecurityEx on IWbemServices void INTFUNC ISAMGetSelectStarList(char** lpWQLSelectStarList, TableColumnInfo* pSelectInfo, LPISAM lpISAM) { //First check you have one table in the select list char* mytable = NULL; BOOL fDummyValue = FALSE; pSelectInfo->BuildTableList(&mytable, fDummyValue); if ( mytable && lstrlen (mytable) ) { //got the table, now fetch the column names CBString pBStrTableName; pBStrTableName.AddString((LPSTR)mytable, FALSE); IWbemContext* pContext = ISAMCreateLocaleIDContextObject(lpISAM->m_Locale); //Get class object based on table name IWbemClassObjectPtr pSingleTable = NULL; IWbemServicesPtr pGateway = NULL; ISAMGetGatewayServer(pGateway, lpISAM, (LPUSTR)lpISAM->szDatabase, (SWORD) lstrlen(lpISAM->szDatabase)); if ( FAILED(pGateway->GetObject(pBStrTableName.GetString(), 0, pContext, &pSingleTable, NULL))) { if (pContext) pContext->Release(); if (mytable) delete mytable; return; } if (pContext) pContext->Release(); //Get the names of all the properties/columns SAFEARRAY FAR* rgSafeArray = NULL; SCODE scT = pSingleTable->GetNames ( NULL, 0, NULL, &rgSafeArray ); //Work out number of properties/columns LONG iLBound = 0; LONG iUBound = 0; SafeArrayGetLBound(rgSafeArray, 1, &iLBound ); SafeArrayGetUBound(rgSafeArray, 1, &iUBound ); //Loop through column names char pColumnName [MAX_COLUMN_NAME_LENGTH+1]; BOOL fFirstTime = TRUE; for (LONG loop = iLBound; loop <= iUBound; loop++) { BSTR lpbString; if ( FAILED(SafeArrayGetElement(rgSafeArray, &loop, &lpbString)) ) { if (mytable) delete mytable; SafeArrayUnlock(rgSafeArray); //SAI ADDED SafeArrayDestroy(rgSafeArray);//SAI ADDED //(11) Should we also release pSingleTable return; } //copy column name pColumnName[0] = 0; wcstombs(pColumnName, lpbString, MAX_COLUMN_NAME_LENGTH); pColumnName[MAX_COLUMN_NAME_LENGTH] = 0; //filters - check for system properties BOOL fAddToList = TRUE; if (! lpISAM->fSysProps && !_strnicmp("__", pColumnName, 2)) { fAddToList = FALSE; } //filters - check for lazy properties if (fAddToList) { BOOL fIsLazyProperty = FALSE; //Now get the qualifiers (if available) IWbemQualifierSet* pQualifierSet = NULL; if ( S_OK == (pSingleTable->GetPropertyQualifierSet (lpbString, &pQualifierSet)) ) { //Get the lazy qualifer (if applicable) VARIANT pValLazy; BSTR lazyStr = SysAllocString(WBEMDR32_L_LAZY); if ( S_OK == (pQualifierSet->Get(lazyStr, 0, &pValLazy, NULL)) ) { fAddToList = FALSE; VariantClear(&pValLazy); } SysFreeString(lazyStr); //Tidy up if (pQualifierSet) pQualifierSet->Release(); } } //add to select list if (fAddToList) { if (!fFirstTime) { ISAMStringConcat(lpWQLSelectStarList, ", "); } ISAMStringConcat(lpWQLSelectStarList, pColumnName); fFirstTime = FALSE; } SysFreeString(lpbString); } } } /***************************************************************************/ SWORD INTFUNC ISAMParameter(LPISAMSTATEMENT lpISAMStatement, UWORD ipar, SWORD fCType, PTR rgbValue, SDWORD cbValue) { lpISAMStatement->lpISAM->errcode = NO_ISAM_ERR; if (fCType != SQL_C_CHAR) { lpISAMStatement->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } if (cbValue > MAX_CHAR_LITERAL_LENGTH) { lpISAMStatement->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } if (cbValue == SQL_NULL_DATA) cbValue = 0; if (ipar == 1) { lpISAMStatement->lpszParam1 = (LPSTR)rgbValue; lpISAMStatement->cbParam1 = cbValue; } else if (ipar == 2) { lpISAMStatement->lpszParam2 = (LPSTR)rgbValue; lpISAMStatement->cbParam2 = cbValue; } else { lpISAMStatement->lpISAM->errcode = ISAM_ERROR; return ISAM_ERROR; } return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMExecute(LPISAMSTATEMENT lpISAMStatement, SDWORD FAR *lpcRowCount) { lpISAMStatement->lpISAM->errcode = NO_ISAM_ERR; if (lpISAMStatement->resultSet) { // *lpcRowCount = 2; //Return number of READ instances //we never know the total number of instances returned //via passthrough SQL (we get them in batches of 10) //*lpcRowCount = lpISAMStatement->pAllRecords->GetCount(); *lpcRowCount = 0; } else { MessageBox(NULL, lpISAMStatement->lpszParam1, lpISAMStatement->lpszParam2, 0); *lpcRowCount = 0; } return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMFreeStatement(LPISAMSTATEMENT lpISAMStatement) { lpISAMStatement->lpISAM->errcode = NO_ISAM_ERR; //Free 1st SQL passthrough instance (if not already freed) if (lpISAMStatement->firstPassthrInst) { lpISAMStatement->firstPassthrInst->Release(); lpISAMStatement->firstPassthrInst = NULL; } //Free Enumeration of Class definitions if (lpISAMStatement->tempEnum) { delete lpISAMStatement->tempEnum; lpISAMStatement->tempEnum = NULL; } if (lpISAMStatement->tempEnum2) { delete lpISAMStatement->tempEnum2; lpISAMStatement->tempEnum2 = NULL; } if (lpISAMStatement->pProv) { delete lpISAMStatement->pProv; lpISAMStatement->pProv = NULL; } if (lpISAMStatement->passthroughMap) { TidyupPassthroughMap(lpISAMStatement->passthroughMap); lpISAMStatement->passthroughMap = NULL; } GlobalUnlock(GlobalPtrHandle(lpISAMStatement)); GlobalFree(GlobalPtrHandle(lpISAMStatement)); return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMSetTxnIsolation(LPISAM lpISAM, UDWORD fTxnIsolationLevel) { /* Select one of the isolation modes from TxnIsolationOption */ if (!(fTxnIsolationLevel & lpISAM->fTxnIsolationOption)) { lpISAM->errcode = ISAM_NOTSUPPORTED; return ISAM_NOTSUPPORTED; } lpISAM->errcode = NO_ISAM_ERR; return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMCommitTxn(LPISAM lpISAM) { lpISAM->errcode = NO_ISAM_ERR; return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMRollbackTxn(LPISAM lpISAM) { lpISAM->errcode = NO_ISAM_ERR; return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMClose(LPISAM lpISAM) { lpISAM->errcode = NO_ISAM_ERR; if (lpISAM->pNamespaceMap) { if (lpISAM->pNamespaceMap->GetCount ()) { CString key; CNamespace *pNamespace; for (POSITION pos = lpISAM->pNamespaceMap->GetStartPosition (); pos != NULL; ) { if (pos) { lpISAM->pNamespaceMap->GetNextAssoc (pos, key, (CObject*&)pNamespace); delete pNamespace; } } } delete lpISAM->pNamespaceMap; } if (lpISAM->m_Locale) { delete (lpISAM->m_Locale); lpISAM->m_Locale = NULL; } if (lpISAM->m_Authority) { delete (lpISAM->m_Authority); lpISAM->m_Authority = NULL; } if (lpISAM->gpAuthIdentity) { WbemFreeAuthIdentity( lpISAM->gpAuthIdentity ); lpISAM->gpAuthIdentity = NULL; } if (lpISAM->Impersonate) { delete (lpISAM->Impersonate); lpISAM->Impersonate = NULL; } if (lpISAM->hKernelApi) { BOOL status = FreeLibrary(lpISAM->hKernelApi); lpISAM->hKernelApi = NULL; if (! status) { DWORD err = GetLastError(); CString message ("\n\n***** FreeLibrary(2) KERNEL32 failed : %ld*****\n\n", err); ODBCTRACE(message); } } GlobalUnlock(GlobalPtrHandle(lpISAM)); GlobalFree(GlobalPtrHandle(lpISAM)); return NO_ISAM_ERR; } /***************************************************************************/ void INTFUNC ISAMGetErrorMessage(LPISAM lpISAM, LPUSTR lpszErrorMessage) { LoadString(s_hModule, lpISAM->errcode, (LPSTR)lpszErrorMessage, MAX_ERROR_LENGTH+1); } /***************************************************************************/ LPSQLTYPE INTFUNC ISAMGetColumnType( LPISAMTABLEDEF lpISAMTableDef, UWORD icol) { /* There may be more than one entry in SQLTypes[] for any given SQL_x type, */ /* therefore we need to compare on the type name string */ ClassColumnInfoBase* cInfoBase = lpISAMTableDef->pColumnInfo; if ( !cInfoBase->IsValid() ) { return NULL; } UWORD cNumberOfCols = cInfoBase->GetNumberOfColumns(); if (icol >= cNumberOfCols) return NULL; UCHAR* puTypeName = NULL; if ( !cInfoBase->GetTypeName(icol, puTypeName) ) { return NULL; } UCHAR szTypeName[MAX_COLUMN_NAME_LENGTH+1]; LONG cLength = strlen ((char*)puTypeName); memcpy(szTypeName, (char*)puTypeName, cLength); szTypeName[cLength] = 0; return GetType2(szTypeName); } /***************************************************************************/ BOOL INTFUNC ISAMCaseSensitive(LPISAM lpISAM) { return FALSE; } /***************************************************************************/ LPUSTR INTFUNC ISAMName(LPISAM lpISAM) { char* pName = new char [3 + 1]; pName[0] = 0; sprintf (pName, "%s", "WMI"); return (LPUSTR)pName; /* char* lpRootDb = (char*)lpISAM->szRootDb; IWbemServices* pProv = ISAMGetGatewayServer(lpISAM, (LPUSTR)lpRootDb, lstrlen(lpRootDb)); if (!pProv) { return NULL; } IWbemClassObject * pClassObj = NULL; char* pName = NULL; BSTR hmomIdBSTR = SysAllocString(WBEMDR32_L_CIMOMIDENTIFICATION); IWbemContext* pContext = ISAMCreateLocaleIDContextObject(lpISAM->m_Locale); SCODE sc = pProv->GetObject(hmomIdBSTR, 0, pContext, &pClassObj, NULL); if (pContext) pContext->Release(); SysFreeString(hmomIdBSTR); if (sc == S_OK) { VARIANTARG var; VariantInit(&var); BSTR serverBSTR = SysAllocString(WBEMDR32_L_SERVER); pClassObj->Get(serverBSTR,0,&var, NULL, NULL); SysFreeString(serverBSTR); LONG lLength = wcslen(var.bstrVal); char* pTemp = new char [lLength + 1]; pTemp[0] = 0; wcstombs(pTemp, var.bstrVal, lLength); pTemp[lLength] = 0; pName = new char [lLength + 10]; pName[0] = 0; lstrcpy(pName, "MOServer@"); lstrcat(pName, pTemp); delete pTemp; VariantClear(&var); pClassObj->Release(); } if (pProv) pProv->Release(); return (LPUSTR)pName; */ } /***************************************************************************/ // Checked for SetInterfaceSecurityEx on IWbemServices LPUSTR INTFUNC ISAMServer(LPISAM lpISAM) { ODBCTRACE("\nWBEM ODBC Driver : ISAMServer\n"); char* lpRootDb = (char*)lpISAM->szRootDb; IWbemServicesPtr pProv = NULL; ISAMGetGatewayServer(pProv, lpISAM, (LPUSTR)lpRootDb, (SWORD) lstrlen(lpRootDb)); if (pProv == NULL) { return NULL; } IWbemClassObject * pClassObj = NULL; char* pName = NULL; BSTR hmomIdBSTR = SysAllocString(WBEMDR32_L_CIMOMIDENTIFICATION); IWbemContext* pContext = ISAMCreateLocaleIDContextObject(lpISAM->m_Locale); SCODE sc = pProv->GetObject(hmomIdBSTR, 0, pContext, &pClassObj, NULL); if (pContext) pContext->Release(); SysFreeString(hmomIdBSTR); if (sc == S_OK) { VARIANTARG var; BSTR serverBSTR = SysAllocString(WBEMDR32_L_SERVER); pClassObj->Get(serverBSTR,0,&var, NULL, NULL); SysFreeString(serverBSTR); LONG lLength = wcslen(var.bstrVal); pName = new char [lLength + 1]; pName[0] = 0; wcstombs(pName, var.bstrVal, lLength); pName[lLength] = 0; VariantClear(&var); long rc = pClassObj->Release(); } return (LPUSTR)pName; } /***************************************************************************/ LPUSTR INTFUNC ISAMVersion(LPISAM lpISAM) { char* pVersion = new char [10 + 1]; pVersion[0] = 0; sprintf (pVersion, "%s", "01.00.0000"); return (LPUSTR)pVersion; } /***************************************************************************/ LPCUSTR INTFUNC ISAMDriver(LPISAM lpISAM) { return (LPCUSTR) "WBEMDR32.DLL"; } /***************************************************************************/ SWORD INTFUNC ISAMMaxTableNameLength(LPISAM lpISAM) { return MAX_TABLE_NAME_LENGTH;//i.e.128 } /***************************************************************************/ SWORD INTFUNC ISAMMaxColumnNameLength(LPISAM lpISAM) { return MAX_COLUMN_NAME_LENGTH;//i.e.128 } /***************************************************************************/ LPUSTR INTFUNC ISAMUser(LPISAM lpISAM) { return (LPUSTR) lpISAM->szUser; } /***************************************************************************/ LPUSTR INTFUNC ISAMDatabase(LPISAM lpISAM) { return (LPUSTR) lpISAM->szDatabase; } /***************************************************************************/ int INTFUNC ISAMSetDatabase (LPISAM lpISAM, LPUSTR database) { if (database && s_lstrlen(database) < MAX_DATABASE_NAME_LENGTH) { s_lstrcpy (lpISAM->szDatabase, database); return TRUE; } else return FALSE; } /***************************************************************************/ LPUSTR INTFUNC ISAMRoot (LPISAM lpISAM) { return (LPUSTR) lpISAM->szRootDb; } /***************************************************************************/ /* This code was copied from the original Dr DeeBee code and moved to */ /* this separate function for our uses */ static SWORD ISAMGetDoubleFromString(BSTR &pString, SDWORD cbValueMax, double &d, BOOL & isNull, BOOL &foundDecimalPoint) { isNull = TRUE; BOOL neg = TRUE; char* pTemp = new char [cbValueMax + 1]; pTemp[0] = 0; SDWORD cbLen = wcstombs( pTemp, pString, cbValueMax); pTemp[cbValueMax] = 0; for (SDWORD i=0; i < cbLen; i++) { if (*pTemp != ' ') break; pTemp++; } neg = FALSE; if (i < cbLen) { if (*pTemp == '-') { neg = TRUE; pTemp++; i++; } } d = 0.0; short scale = 0; BOOL negexp = FALSE; foundDecimalPoint = FALSE; for (;i < cbLen; i++) { if (!foundDecimalPoint && (*pTemp == '.')) foundDecimalPoint = TRUE; else { if ((*pTemp == 'E') || (*pTemp == 'e')) { pTemp++; i++; if (i < cbLen) { if (*pTemp == '-') { negexp = TRUE; pTemp++; i++; } else if (*pTemp == '+') { negexp = FALSE; pTemp++; i++; } else negexp = FALSE; } else negexp = FALSE; short exp = 0; for (;i < cbLen; i++) { if ((*pTemp < '0') || (*pTemp > '9')) { delete pTemp; return DBASE_ERR_CONVERSIONERROR; } exp = (exp * 10) + (*pTemp - '0'); pTemp++; } if (negexp) scale = scale + exp; else scale = scale - exp; break; } if ((*pTemp < '0') || (*pTemp > '9')) { delete pTemp; return DBASE_ERR_CONVERSIONERROR; } d = (d * 10) + (*pTemp - '0'); isNull = FALSE; if (foundDecimalPoint) scale++; } pTemp++; } for (; (0 < scale); scale--) d /= 10; for (; (0 > scale); scale++) d *= 10; if (neg) d = -d; delete pTemp; return DBASE_ERR_SUCCESS; } /***************************************************************************/ /* Template class to decode array variant value */ /* */ /* The fIsBinaryOutput parameter indicates if you */ /* want the output value a binary data or a string */ template SWORD ISAMGetArrayInfo (VARIANT &vVariantVal, T theValue, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR* pcbValue, BOOL fIsBinaryOutput, SWORD wDSDT, UDWORD cbPrecision, long myVirIndex = -1) { //Check if we want all elements of the array or just one element BOOL fAllElements = TRUE; if (myVirIndex != -1) { fAllElements = FALSE; } //Get the value SAFEARRAY FAR* pArray = vVariantVal.parray; SafeArrayLock(pArray); //Find out the bounds of the array //Get the upper and lower bounds long lLowerBound; SafeArrayGetLBound(pArray, 1, &lLowerBound); long lUpperBound; SafeArrayGetUBound(pArray, 1, &lUpperBound); *pcbValue = 0; if (cbValueMax) ((char*)rgbValue)[0] = 0; //Initialize long cCount = 0; SWORD wElemSize = sizeof (T); //Setup the filter for the data char filter [20]; filter[0] = 0; //Character string length use to represent each element of array SWORD wFullCharSize = 0; if (!fIsBinaryOutput) { //Also setup the filter for the data filter[0] = 0; if ( wDSDT == WBEM_DSDT_REAL_ARRAY ) { if (fAllElements) { //For character string output the format will be [precision.6f] //Thus, we need room for the [ ] and the 'precision.6' wFullCharSize = 9 + REAL_PRECISION; sprintf (filter, "%s%d%s", "[%", REAL_PRECISION, ".6g]"); } else { //For character string output the format will be precision.6f //Thus, we need room for the 'precision.6' wFullCharSize = 7 + REAL_PRECISION; sprintf (filter, "%s%d%s", "%", REAL_PRECISION, ".6g"); } } else if ( wDSDT == WBEM_DSDT_DOUBLE_ARRAY ) { if (fAllElements) { //For character string output the format will be [precision.6f] //Thus, we need room for the [ ] and the 'precision.6' wFullCharSize = 9 + DOUBLE_PRECISION; sprintf (filter, "%s%d%s", "[%", DOUBLE_PRECISION, ".6g]"); } else { //For character string output the format will be precision.6f //Thus, we need room for the 'precision.6' wFullCharSize = 7 + DOUBLE_PRECISION; sprintf (filter, "%s%d%s", "%", DOUBLE_PRECISION, ".6g"); } } else { //For character string output the format will be [precision] //We add 1 to the precision if the type is signed //Thus, we need room for the [ ] and the //ie 2 extra characters for unsigned and 3 for signed //Integer type //Check if signed switch (wDSDT) { case WBEM_DSDT_SINT8_ARRAY: case WBEM_DSDT_SINT16_ARRAY: case WBEM_DSDT_SINT32_ARRAY: { //Signed ++cbPrecision; if (fAllElements) { wFullCharSize = (SWORD) (cbPrecision + 2); strcpy (filter, "[%ld]"); } else { wFullCharSize = (SWORD) cbPrecision; strcpy (filter, "%ld"); } } break; case WBEM_DSDT_BOOL_ARRAY: { if (fAllElements) { wFullCharSize = (SWORD) (cbPrecision + 2); strcpy (filter, "[%s]"); } else { wFullCharSize = (SWORD) cbPrecision; strcpy (filter, "%s"); } } break; default: { if (fAllElements) { //Unsigned wFullCharSize = (SWORD) (cbPrecision + 2); strcpy (filter, "[%lu]"); } else { //Unsigned wFullCharSize = (SWORD) (cbPrecision); strcpy (filter, "%lu"); } } break; } } } char* tempBuff = new char [wFullCharSize + 1]; //Loop through each entry to fetch the array data BOOL fDoweHaveEnoughBufferSpace = FALSE; long loop = 0; for (long cIndex = lLowerBound; cIndex <= lUpperBound; cIndex++) { //Check we have enough buffer space if (fIsBinaryOutput) { fDoweHaveEnoughBufferSpace = ((wElemSize + (*pcbValue)) <= cbValueMax) ? TRUE : FALSE; } else { fDoweHaveEnoughBufferSpace = ((wFullCharSize + (*pcbValue)) <= cbValueMax) ? TRUE : FALSE; } if ( fDoweHaveEnoughBufferSpace) { if ( SUCCEEDED(SafeArrayGetElement(pArray, &cIndex, &theValue)) ) { //Check if we want to use this value BOOL fUseThisValue = FALSE; if (fAllElements) { fUseThisValue = TRUE; } else { if (loop == myVirIndex) fUseThisValue = TRUE; } if (fUseThisValue) { if (fIsBinaryOutput) { //Copy T* pTemp = (T*)rgbValue; pTemp[cCount++] = theValue; //Increment counter of number of bytes copied (*pcbValue) += wElemSize; } else { tempBuff[0] = 0; if (wDSDT == WBEM_DSDT_BOOL_ARRAY) { sprintf (tempBuff, filter, (theValue ? "T" : "F")); } else { sprintf (tempBuff, filter, (T) theValue); } lstrcat( (char*)rgbValue, tempBuff); //Increment counter of number of bytes copied (*pcbValue) += lstrlen (tempBuff); } } } else { //error !!! //Tidy Up delete tempBuff; SafeArrayUnlock(pArray); return ISAM_ERROR; } } else { //No we don't so quit //Tidy Up delete tempBuff; SafeArrayUnlock(pArray); return ISAM_TRUNCATION; } loop++; } //Tidy Up delete tempBuff; SafeArrayUnlock(pArray); return NO_ISAM_ERR; } /**************************************************************************/ SWORD INTFUNC ISAMGetArrayStringInfo (VARIANT &vVariantVal, BSTR syntaxStr, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR* pcbValue, BOOL fIsBinaryOutput, long myVirIndex) { //Check if we want all elements of the array or just one element BOOL fAllElements = TRUE; if (myVirIndex != -1) { fAllElements = FALSE; } //Get the value SAFEARRAY FAR* pArray = vVariantVal.parray; SafeArrayLock(pArray); //Find out the bounds of the array //Get the upper and lower bounds long lLowerBound; SafeArrayGetLBound(pArray, 1, &lLowerBound); long lUpperBound; SafeArrayGetUBound(pArray, 1, &lUpperBound); *pcbValue = 0; //Initialize long cCount = 0; BSTR theValue; ((char*)rgbValue)[0] = 0; BOOL fOutOfBufferSpace = FALSE; long loop = 0; for (long cIndex = lLowerBound; (!fOutOfBufferSpace) && (cIndex <= lUpperBound); cIndex++) { //Check if we want to use this value BOOL fUseThisValue = FALSE; if (fAllElements) { fUseThisValue = TRUE; } else { if (loop == myVirIndex) fUseThisValue = TRUE; } if (fUseThisValue) { if ( SUCCEEDED(SafeArrayGetElement(pArray, &cIndex, &theValue)) ) { //Now we must add in string value in the format [string] //However, if the string contains either [ or ] we must double //this character in the string sequence ULONG cLength = 0; char* theValueStr = NULL; if (theValue) { cLength = wcslen(theValue); theValueStr = new char [cLength + 1]; theValueStr[0] = 0; wcstombs(theValueStr, theValue, cLength); theValueStr[cLength] = 0; } SWORD err = NO_ISAM_ERR; if (!syntaxStr) syntaxStr = L" "; //Check if this is a string, timestamp, interval, time or date BOOL foundMatch = FALSE; // if ( (_wcsicmp(syntaxStr, WBEM_WSYNTAX_DATETIME) == 0) || // (_wcsicmp(syntaxStr, WBEM_WSYNTAX_INTERVAL) == 0)) if (_wcsicmp(syntaxStr, WBEM_WSYNTAX_DATETIME) == 0) { //A timestamp DateTimeParser parser(theValue); // if ( parser.IsValid() && parser.IsTimestamp() ) { foundMatch = TRUE; if (fIsBinaryOutput) { if (cbValueMax >= (SDWORD)((*pcbValue) + sizeof (TIMESTAMP_STRUCT)) ) { TIMESTAMP_STRUCT FAR* pTimeStampStruct = (TIMESTAMP_STRUCT FAR*)((char*)rgbValue + (*pcbValue)); pTimeStampStruct->year = (SWORD)parser.GetYear(); pTimeStampStruct->month = (UWORD)parser.GetMonth(); pTimeStampStruct->day = (UWORD)parser.GetDay(); pTimeStampStruct->hour = (UWORD)parser.GetHour(); pTimeStampStruct->minute = (UWORD)parser.GetMin(); pTimeStampStruct->second = (UWORD)parser.GetSec(); pTimeStampStruct->fraction = 1000 * parser.GetMicroSec(); *pcbValue += sizeof (TIMESTAMP_STRUCT); } else { //not enough space err = ISAM_TRUNCATION; } } else { TIMESTAMP_STRUCT pTimeStampStruct; pTimeStampStruct.year = (SWORD)parser.GetYear(); pTimeStampStruct.month = (UWORD)parser.GetMonth(); pTimeStampStruct.day = (UWORD)parser.GetDay(); pTimeStampStruct.hour = (UWORD)parser.GetHour(); pTimeStampStruct.minute = (UWORD)parser.GetMin(); pTimeStampStruct.second = (UWORD)parser.GetSec(); pTimeStampStruct.fraction = 1000 * parser.GetMicroSec(); if (fAllElements) { if (cbValueMax >= ( (*pcbValue) + 23+TIMESTAMP_SCALE) ) { char szBuffer[20+TIMESTAMP_SCALE+1]; TimestampToChar(&pTimeStampStruct, (LPUSTR)szBuffer); char* ptrToStr = ((char*)rgbValue + (*pcbValue)); sprintf (ptrToStr, "[%s]", szBuffer); *pcbValue += (22+TIMESTAMP_SCALE); //ignore null } else { //not enough space err = ISAM_TRUNCATION; } } else { if (cbValueMax >= ( (*pcbValue) + 21+TIMESTAMP_SCALE) ) { char szBuffer[20+TIMESTAMP_SCALE+1]; TimestampToChar(&pTimeStampStruct, (LPUSTR)szBuffer); char* ptrToStr = ((char*)rgbValue + (*pcbValue)); sprintf (ptrToStr, "%s", szBuffer); *pcbValue += (20+TIMESTAMP_SCALE); //ignore null } else { //not enough space err = ISAM_TRUNCATION; } } } } } /* else if (_wcsicmp(syntaxStr, WBEM_WSYNTAX_DATE) == 0) { //A date DateTimeParser parser(theValue); // if ( parser.IsValid() && parser.IsDate() ) { foundMatch = TRUE; if (fIsBinaryOutput) { if (cbValueMax >= (SDWORD)((*pcbValue) + sizeof (DATE_STRUCT)) ) { DATE_STRUCT FAR* pDateStruct = (DATE_STRUCT FAR*)((char*)rgbValue + (*pcbValue)); pDateStruct->year = (SWORD)parser.GetYear(); pDateStruct->month = (UWORD)parser.GetMonth(); pDateStruct->day = (UWORD)parser.GetDay(); *pcbValue += sizeof (DATE_STRUCT); } else { //not enough space err = ISAM_TRUNCATION; } } else { DATE_STRUCT pDateStruct; pDateStruct.year = (SWORD)parser.GetYear(); pDateStruct.month = (UWORD)parser.GetMonth(); pDateStruct.day = (UWORD)parser.GetDay(); if (cbValueMax >= ( (*pcbValue) + 3 + DATE_PRECISION) ) { char szBuffer[DATE_PRECISION + 1]; DateToChar(&pDateStruct, szBuffer); char* ptrToStr = ((char*)rgbValue + (*pcbValue)); sprintf (ptrToStr, "[%s]", szBuffer); *pcbValue += (2 + DATE_PRECISION);// ignore null } else { //not enough space err = ISAM_TRUNCATION; } } } } else if (_wcsicmp(syntaxStr, WBEM_WSYNTAX_TIME) == 0) { //A time DateTimeParser parser(theValue); // if ( parser.IsValid() && parser.IsTime() ) { foundMatch = TRUE; if (fIsBinaryOutput) { if (cbValueMax >= (SDWORD)((*pcbValue) + sizeof (TIME_STRUCT)) ) { TIME_STRUCT FAR* pTimeStruct = (TIME_STRUCT FAR*)((char*)rgbValue + (*pcbValue)); pTimeStruct->hour = (UWORD)parser.GetHour(); pTimeStruct->minute = (UWORD)parser.GetMin(); pTimeStruct->second = (UWORD)parser.GetSec(); *pcbValue += sizeof (TIME_STRUCT); } else { //not enough space err = ISAM_TRUNCATION; } } else { TIME_STRUCT pTimeStruct; pTimeStruct.hour = (UWORD)parser.GetHour(); pTimeStruct.minute = (UWORD)parser.GetMin(); pTimeStruct.second = (UWORD)parser.GetSec(); if (cbValueMax >= ( (*pcbValue) + 3 + TIME_PRECISION) ) { char szBuffer[TIME_PRECISION + 1]; TimeToChar(&pTimeStruct, szBuffer); char* ptrToStr = ((char*)rgbValue + (*pcbValue)); sprintf (ptrToStr, "[%s]", szBuffer); *pcbValue += (2 + TIME_PRECISION);//ignore null } else { //not enough space err = ISAM_TRUNCATION; } } } } */ if (!foundMatch) { //Check if string or 64bit integer SDWORD fInt64Check = 0; if ( (_wcsicmp(syntaxStr, WBEM_WSYNTAX_SINT64) == 0) ) fInt64Check = WBEM_DSDT_SINT64; if ( (_wcsicmp(syntaxStr, WBEM_WSYNTAX_UINT64) == 0) ) fInt64Check = WBEM_DSDT_UINT64; err = ISAMFormatCharParm (theValueStr, fOutOfBufferSpace, (char*)rgbValue, cbValueMax, pcbValue, fIsBinaryOutput, fInt64Check, fAllElements); } if (theValue) delete theValueStr; //SAI MOVED SysFreeString(theValue); if (err != NO_ISAM_ERR) { SafeArrayUnlock(pArray); return err; } } else { //error !!! SafeArrayUnlock(pArray); return ISAM_ERROR; } } loop++; } //Tidy Up // SysFreeString(theValue); SafeArrayUnlock(pArray); return NO_ISAM_ERR; } /* SWORD ISAMGetPropertyArrayInfo(BSTR & arrayVal, SWORD fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR *pcbValue, SWORD wbemVariantType, BSTR syntaxStr, BSTR maxStr) { SWORD err = NO_ISAM_ERR; SWORD wDSDT = 0; SWORD dummy1 = 0; UDWORD cbPrecision = 0; //Get the value BSTR pString = arrayVal; //If no WBEM variant type specified use default if (!wbemVariantType) wbemVariantType = WBEM_VARIANT_VT_ARRAY_BSTR; //How do we want the value returned switch (fCType) { case SQL_C_DOUBLE: { double dVal; BOOL foundDecimalPoint; BOOL isNull; *pcbValue = sizeof(double); if ((cbValueMax >= *pcbValue) && (DBASE_ERR_SUCCESS == ISAMGetDoubleFromString(pString, cbValueMax, dVal, isNull, foundDecimalPoint)) ) { if (isNull) { *pcbValue = SQL_NULL_DATA; } else { *((double *)rgbValue) = dVal; } } else { *pcbValue = 0; return ERR_NOTCONVERTABLE; } } break; case SQL_C_CHAR: { char* pTemp = (char*) rgbValue; pTemp[0] = 0; *pcbValue = wcstombs( pTemp, pString, cbValueMax); //Make an extra check here if you are requesting 64bit integers ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxStr, wDSDT, dummy1, cbPrecision); //Check for numeric string if ( (wDSDT == WBEM_DSDT_SINT64_ARRAY) ) { for (SDWORD ii = 0; ii < (*pcbValue); ii++) { switch (pTemp[ii]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '+': case '-': //OK break; default: return ERR_INVALID_INTEGER; break; } } } if ( (wDSDT == WBEM_DSDT_UINT64_ARRAY) ) { for (SDWORD ii = 0; ii < (*pcbValue); ii++) { switch (pTemp[ii]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': //OK break; default: return ERR_INVALID_INTEGER; break; } } } } break; case SQL_C_TIMESTAMP: { //Check that you have enough buffer to store value *pcbValue = sizeof (TIMESTAMP_STRUCT); TIMESTAMP_STRUCT FAR* pTimeStampStruct = (TIMESTAMP_STRUCT FAR*)rgbValue; if ( cbValueMax >= (*pcbValue) ) { DateTimeParser parser(pString); // if ( parser.IsValid() && parser.IsTimestamp() ) { pTimeStampStruct->year = (SWORD)parser.GetYear(); pTimeStampStruct->month = (UWORD)parser.GetMonth(); pTimeStampStruct->day = (UWORD)parser.GetDay(); pTimeStampStruct->hour = (UWORD)parser.GetHour(); pTimeStampStruct->minute = (UWORD)parser.GetMin(); pTimeStampStruct->second = (UWORD)parser.GetSec(); pTimeStampStruct->fraction = 1000 * parser.GetMicroSec(); } } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } break; case SQL_C_BINARY: default: { //No convertion available return ERR_NOTCONVERTABLE; } break; } return err; } */ /***************************************************************************/ /* Retrieves the value from a variant */ SWORD ISAMGet_VT_I2(short iShortVal, SWORD fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR *pcbValue, SWORD wbemVariantType, BSTR syntaxStr, SDWORD maxLenVal) { SWORD err = NO_ISAM_ERR; SWORD wDSDT = 0; SWORD dummy1 = 0; UDWORD cbPrecision = 0; //If no WBEM variant type specified use default if (!wbemVariantType) wbemVariantType = WBEM_VARIANT_VT_I2; //How do we want the value returned switch (fCType) { case SQL_C_DOUBLE: { //Check that you have enough buffer to store value ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); if ( (wDSDT == WBEM_DSDT_SINT8) || (wDSDT == WBEM_DSDT_SINT8_ARRAY) ) { //Signed 8 bit value //Check that you have enough buffer to store value *pcbValue = sizeof(signed char); if (cbValueMax >= *pcbValue) { signed char iCharVal = (signed char) iShortVal; *((double *)rgbValue) = (double)iCharVal; } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } else { //Signed 16 bit value //Check that you have enough buffer to store value *pcbValue = sizeof(double); if (cbValueMax >= *pcbValue) { *((double *)rgbValue) = (double)iShortVal; } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } } break; case SQL_C_CHAR: { ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); if ( (wDSDT == WBEM_DSDT_SINT8) || (wDSDT == WBEM_DSDT_SINT8_ARRAY) ) { //Signed 8 bit value //Check that there is enough buffer space for largest value if (cbValueMax >= STINYINT_PRECISION) { char ttt = (char) iShortVal; char* pTemp = (char*)rgbValue; pTemp[0] = 0; sprintf ((char*)rgbValue, "%d", (short)ttt); *pcbValue = lstrlen(pTemp); } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } else { //Signed 16 bit value //Check that there is enough buffer space for largest value if (cbValueMax >= SSHORT_PRECISION) { char* pTemp = (char*)rgbValue; pTemp[0] = 0; sprintf ((char*)rgbValue, "%ld", iShortVal); *pcbValue = lstrlen(pTemp); } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } } break; case SQL_C_DATE: case SQL_C_TIME: case SQL_C_TIMESTAMP: case SQL_C_BINARY: default: { //No convertion available return ISAM_ERROR; } break; } return err; } SWORD ISAMGet_VT_UI1(UCHAR iUcharVal, SWORD fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR *pcbValue, SWORD wbemVariantType, BSTR syntaxStr, SDWORD maxLenVal) { SWORD err = NO_ISAM_ERR; SWORD wDSDT = 0; SWORD dummy1 = 0; UDWORD cbPrecision = 0; //If no WBEM variant type specified use default if (!wbemVariantType) wbemVariantType = WBEM_VARIANT_VT_UI1; //How do we want the value returned switch (fCType) { case SQL_C_DOUBLE: { *pcbValue = sizeof(double); //Check that you have enough buffer to store value if (cbValueMax >= *pcbValue) { ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); { //Unsigned 8 bit value *((double *)rgbValue) = (double)iUcharVal; } } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } break; case SQL_C_CHAR: { ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); if (cbValueMax >= UTINYINT_PRECISION) { //Unsigned 8 bit value //Check that there is enough buffer space for largest value char* pTemp = (char*)rgbValue; pTemp[0] = 0; _itoa(iUcharVal, pTemp, 10); *pcbValue = lstrlen(pTemp); } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } break; case SQL_C_DATE: case SQL_C_TIME: case SQL_C_TIMESTAMP: case SQL_C_BINARY: default: { //No convertion available return ERR_NOTCONVERTABLE; } break; } return err; } SWORD ISAMGet_VT_I4(long iValue, SWORD fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR *pcbValue, SWORD wbemVariantType, BSTR syntaxStr, SDWORD maxLenVal) { SWORD err = NO_ISAM_ERR; SWORD wDSDT = 0; SWORD dummy1 = 0; UDWORD cbPrecision = 0; //If no WBEM variant type specified use default if (!wbemVariantType) wbemVariantType = WBEM_VARIANT_VT_I4; //How do we want the value returned switch (fCType) { case SQL_C_DOUBLE: { ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); *pcbValue = sizeof (double); if ( (wDSDT == WBEM_DSDT_UINT16) || (wDSDT == WBEM_DSDT_UINT16_ARRAY) ) { //Unsigned 16 bit value //Check that there is enough buffer space for largest value if (cbValueMax >= *pcbValue) { double dd = (unsigned short) iValue; *((double *)rgbValue) = dd; } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } else if ( (wDSDT == WBEM_DSDT_UINT32) || (wDSDT == WBEM_DSDT_UINT32_ARRAY) ) { //Unsigned 32 bit value //Check that you have enough buffer to store value *pcbValue = sizeof (double); if (cbValueMax >= *pcbValue) { double dd = (unsigned long) iValue; *((double *)rgbValue) = dd; } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } else { //Signed 32 bit value //Check that you have enough buffer to store value if (cbValueMax >= *pcbValue) { *((double *)rgbValue) = (double)iValue; } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } } break; case SQL_C_CHAR: { ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); if ( (wDSDT == WBEM_DSDT_UINT16) || (wDSDT == WBEM_DSDT_UINT16_ARRAY) ) { //Unsigned 16 bit value //Check that there is enough buffer space for largest value if (cbValueMax >= USHORT_PRECISION) { unsigned short iushort = (unsigned short) iValue; char* pTemp = (char*)rgbValue; pTemp[0] = 0; sprintf ((char*)rgbValue, "%lu", iushort); *pcbValue = lstrlen(pTemp); } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } else if ( (wDSDT == WBEM_DSDT_UINT32) || (wDSDT == WBEM_DSDT_UINT32_ARRAY) ) { //Unsigned 32 bit value //Check that there is enough buffer space for largest value if (cbValueMax >= ULONG_PRECISION) { unsigned long iulong = (unsigned long) iValue; char* pTemp = (char*)rgbValue; pTemp[0] = 0; sprintf ((char*)rgbValue, "%lu", iulong); *pcbValue = lstrlen(pTemp); } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } else { //Signed 32 bit value //Check that there is enough buffer space for largest value if (cbValueMax >= SLONG_PRECISION) { char* pTemp = (char*)rgbValue; pTemp[0] = 0; sprintf ((char*)rgbValue, "%ld", iValue); *pcbValue = lstrlen(pTemp); } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } } break; case SQL_C_DATE: case SQL_C_TIME: case SQL_C_TIMESTAMP: case SQL_C_BINARY: default: { //No convertion available return ERR_NOTCONVERTABLE; } break; } return err; } SWORD ISAMGet_VT_BOOL(VARIANT_BOOL fBool, SWORD fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR *pcbValue, SWORD wbemVariantType, BSTR syntaxStr, SDWORD maxLenVal) { SWORD err = NO_ISAM_ERR; SWORD wDSDT = 0; SWORD dummy1 = 0; UDWORD cbPrecision = 0; //How do we want the value returned switch (fCType) { case SQL_C_DOUBLE: { *pcbValue = sizeof(double); //Check that you have enough buffer to store value if (cbValueMax >= *pcbValue) { if (fBool) *((double *)rgbValue) = 1.0; else *((double *)rgbValue) = 0.0; } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } break; case SQL_C_CHAR: { if (cbValueMax) { char* pTemp = (char*)rgbValue; pTemp[0] = 0; if (fBool) lstrcpy(pTemp, "T"); else lstrcpy(pTemp, "F"); *pcbValue = 1; } } break; case SQL_C_DATE: case SQL_C_TIME: case SQL_C_TIMESTAMP: case SQL_C_BINARY: default: { //No convertion available return ERR_NOTCONVERTABLE; } break; } return err; } SWORD ISAMGet_VT_R4(float fltVal, SWORD fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR *pcbValue, SWORD wbemVariantType, BSTR syntaxStr, SDWORD maxLenVal) { SWORD err = NO_ISAM_ERR; SWORD wDSDT = 0; SWORD dummy1 = 0; UDWORD cbPrecision = 0; //How do we want the value returned switch (fCType) { case SQL_C_DOUBLE: { *pcbValue = sizeof(double); //Check that you have enough buffer to store value if (cbValueMax >= *pcbValue) { *((double *)rgbValue) = (double)fltVal; } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } break; case SQL_C_CHAR: { int decimal, sign; double dblVal = fltVal; char* buffer = _ecvt(dblVal, cbValueMax - 2, &decimal, &sign); char* pTemp = (char*) rgbValue; pTemp[0] = 0; //We need a buffer to store at least "-.3" if (cbValueMax < 3) { *pcbValue = 0; return ERR_INSUFF_BUFFER; } //Check if value is negative if (sign) { strcpy(pTemp, "-"); } //Now copy digits BEFORE the decimal point if (cbValueMax && decimal) { strncat(pTemp, buffer, decimal); } char* pt = buffer + decimal; if (cbValueMax && strlen (pt) ) { //Add the decimal point strcat (pTemp, "."); //Copy digits AFTER decimal point strcat(pTemp, pt); } *pcbValue = strlen (pTemp); } break; case SQL_C_DATE: case SQL_C_TIME: case SQL_C_TIMESTAMP: case SQL_C_BINARY: default: { //No convertion available return ERR_NOTCONVERTABLE; } break; } return err; } SWORD ISAMGet_VT_R8(double dblVal, SWORD fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR *pcbValue, SWORD wbemVariantType, BSTR syntaxStr, SDWORD maxLenVal) { SWORD err = NO_ISAM_ERR; SWORD wDSDT = 0; SWORD dummy1 = 0; UDWORD cbPrecision = 0; //How do we want the value returned switch (fCType) { case SQL_C_DOUBLE: case SQL_C_DEFAULT: { *pcbValue = sizeof(double); //Check that you have enough buffer to store value if (cbValueMax >= *pcbValue) { *((double *)rgbValue) = (double)dblVal; } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } break; case SQL_C_CHAR: { int decimal, sign; char* buffer = _ecvt(dblVal, cbValueMax - 2, &decimal, &sign); char* pTemp = (char*) rgbValue; pTemp[0] = 0; //We need a buffer to store at least "-.3" if (cbValueMax < 3) { *pcbValue = 0; return ERR_INSUFF_BUFFER; } //Check if value is negative if (sign) { strcpy(pTemp, "-"); } //Now copy digits BEFORE the decimal point if (cbValueMax && decimal) { strncat(pTemp, buffer, decimal); } char* pt = buffer + decimal; if (cbValueMax && strlen (pt) ) { //Add the decimal point strcat (pTemp, "."); //Copy digits AFTER decimal point strcat(pTemp, pt); } *pcbValue = strlen (pTemp); } break; case SQL_C_DATE: case SQL_C_TIME: case SQL_C_TIMESTAMP: case SQL_C_BINARY: default: { //No convertion available return ERR_NOTCONVERTABLE; } break; } return err; } SWORD ISAMGet_VT_BSTR(BSTR pString, SWORD fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR *pcbValue, SWORD wbemVariantType, BSTR syntaxStr, SDWORD maxLenVal) { SWORD err = NO_ISAM_ERR; SWORD wDSDT = 0; SWORD dummy1 = 0; UDWORD cbPrecision = 0; //If no WBEM variant type specified use default if (!wbemVariantType) wbemVariantType = WBEM_VARIANT_VT_BSTR; //How do we want the value returned switch (fCType) { case SQL_C_DOUBLE: { double dVal; BOOL foundDecimalPoint; BOOL isNull; *pcbValue = sizeof(double); if ((cbValueMax >= *pcbValue) && (DBASE_ERR_SUCCESS == ISAMGetDoubleFromString(pString, cbValueMax, dVal, isNull, foundDecimalPoint)) ) { if (isNull) { *pcbValue = SQL_NULL_DATA; } else { *((double *)rgbValue) = dVal; } } else { *pcbValue = 0; return ERR_NOTCONVERTABLE; } } break; case SQL_C_CHAR: { char* pTemp = (char*) rgbValue; _bstr_t myValue((BSTR)pString); *pcbValue = Utility_WideCharToDBCS(myValue, &pTemp, cbValueMax); //Make an extra check here if you are requesting 64bit integers ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); //Check for numeric string if ( (wDSDT == WBEM_DSDT_SINT64) ) { for (SDWORD ii = 0; ii < (*pcbValue); ii++) { switch (pTemp[ii]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '+': case '-': //OK break; default: return ERR_INVALID_INTEGER; break; } } } if ( (wDSDT == WBEM_DSDT_UINT64) ) { for (SDWORD ii = 0; ii < (*pcbValue); ii++) { switch (pTemp[ii]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': //OK break; default: return ERR_INVALID_INTEGER; break; } } } } break; /* case SQL_C_DATE: { //Check that you have enough buffer to store value *pcbValue = sizeof (DATE_STRUCT); DATE_STRUCT FAR* pDateStruct = (DATE_STRUCT FAR*)rgbValue; if ( cbValueMax >= (*pcbValue) ) { DateTimeParser parser(pString); // if ( parser.IsValid() && parser.IsDate() ) { pDateStruct->year = (SWORD)parser.GetYear(); pDateStruct->month = (UWORD)parser.GetMonth(); pDateStruct->day = (UWORD)parser.GetDay(); } // else // { // *pcbValue = 0; // return ERR_INVALID_DATE; // } } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } break; case SQL_C_TIME: { //Check that you have enough buffer to store value *pcbValue = sizeof (TIME_STRUCT); TIME_STRUCT FAR* pTimeStruct = (TIME_STRUCT FAR*)rgbValue; if ( cbValueMax >= (*pcbValue) ) { DateTimeParser parser(pString); // if ( parser.IsValid() && parser.IsTime() ) { pTimeStruct->hour = (UWORD)parser.GetHour(); pTimeStruct->minute = (UWORD)parser.GetMin(); pTimeStruct->second = (UWORD)parser.GetSec(); } // else // { // *pcbValue = 0; // return ERR_INVALID_TIME; // } } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } break; */ case SQL_C_TIMESTAMP: { //Check that you have enough buffer to store value *pcbValue = sizeof (TIMESTAMP_STRUCT); TIMESTAMP_STRUCT FAR* pTimeStampStruct = (TIMESTAMP_STRUCT FAR*)rgbValue; if ( cbValueMax >= (*pcbValue) ) { DateTimeParser parser(pString); // if ( parser.IsValid() && parser.IsTimestamp() ) { pTimeStampStruct->year = (SWORD)parser.GetYear(); pTimeStampStruct->month = (UWORD)parser.GetMonth(); pTimeStampStruct->day = (UWORD)parser.GetDay(); pTimeStampStruct->hour = (UWORD)parser.GetHour(); pTimeStampStruct->minute = (UWORD)parser.GetMin(); pTimeStampStruct->second = (UWORD)parser.GetSec(); pTimeStampStruct->fraction = 1000 * parser.GetMicroSec(); } // else // { // *pcbValue = 0; // return ERR_INVALID_TIMESTAMP; // } } else { *pcbValue = 0; return ERR_INSUFF_BUFFER; } } break; case SQL_C_BINARY: default: { //No convertion available return ERR_NOTCONVERTABLE; } break; } return err; } SWORD ISAMGetValueFromVariant(VARIANT &vVariantVal, SWORD fCType, PTR rgbValue, SDWORD cbValueMax, SDWORD FAR *pcbValue, SWORD wbemVariantType, BSTR syntaxStr, SDWORD maxLenVal, long myVirIndex) { SWORD err = NO_ISAM_ERR; SWORD wDSDT = 0; SWORD dummy1 = 0; UDWORD cbPrecision = 0; VARTYPE varType1 = V_VT(&vVariantVal); switch( varType1 ) { case VT_NULL: { *pcbValue = SQL_NULL_DATA; } break; case VT_I2: { //Get the value short iShortVal = vVariantVal.iVal; err = ISAMGet_VT_I2(iShortVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); } break; case VT_I4: { //Get the value long iValue = vVariantVal.lVal; err = ISAMGet_VT_I4(iValue, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); } break; case VT_UI1: { //Get the value UCHAR iUcharVal = vVariantVal.bVal; err = ISAMGet_VT_UI1(iUcharVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); } break; case VT_BSTR: { //Get the value BSTR pString = vVariantVal.bstrVal; err = ISAMGet_VT_BSTR(pString, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); //Null terminate this string if (cbValueMax > *pcbValue) { ((char*)rgbValue)[*pcbValue] = '\0'; // ODBCTRACE (_T("Null terminating this string")); } else { // ODBCTRACE (_T("Not Null terminating this string")); } } break; case VT_R8: { //Get the value double dblVal = vVariantVal.dblVal; err = ISAMGet_VT_R8(dblVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); } break; case VT_R4: { //Get the value float fltVal = vVariantVal.fltVal; err = ISAMGet_VT_R4(fltVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); } break; case VT_BOOL: { //Get the value VARIANT_BOOL fBool = vVariantVal.boolVal; err = ISAMGet_VT_BOOL(fBool, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); } break; default: { //Before we quit, check whether it is a VT_ARRAY BOOL fIsVT_ARRAY = FALSE; SWORD wStatus = ISAM_ERROR; BOOL fIsBinaryOutput = (fCType == SQL_C_BINARY); if ( varType1 == (VT_ARRAY|VT_UI1 )) { //If no WBEM variant type specified use default if (!wbemVariantType) wbemVariantType = WBEM_VARIANT_VT_ARRAY_UI1; ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); //Get the precision for a single item in array { UCHAR ubVal = 0; cbPrecision = UTINYINT_PRECISION; if (myVirIndex == -1) { //String display for all elements wStatus = ISAMGetArrayInfo (vVariantVal, ubVal, rgbValue, cbValueMax, pcbValue, fIsBinaryOutput, wDSDT, cbPrecision, myVirIndex); } else { //others SAFEARRAY FAR* pArray = vVariantVal.parray; if ( SUCCEEDED(SafeArrayGetElement(pArray, &myVirIndex, &ubVal)) ) { err = ISAMGet_VT_UI1(ubVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); wStatus = NO_ISAM_ERR; if (err == ERR_INSUFF_BUFFER) wStatus = ISAM_TRUNCATION; if (err == ISAM_ERROR) wStatus = ISAM_ERROR; } } } } else if (( varType1 == (VT_ARRAY|VT_I4))) { //If no WBEM variant type specified use default if (!wbemVariantType) wbemVariantType = WBEM_VARIANT_VT_ARRAY_I4; ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); //Get the precision for a single item in array if (wDSDT == WBEM_DSDT_UINT16_ARRAY) { USHORT wVal = 0; cbPrecision = SMALLINT_PRECISION; if (myVirIndex == -1) { //String display for all elements wStatus = ISAMGetArrayInfo (vVariantVal, wVal, rgbValue, cbValueMax, pcbValue, fIsBinaryOutput, wDSDT, cbPrecision, myVirIndex); } else { //others SAFEARRAY FAR* pArray = vVariantVal.parray; if ( SUCCEEDED(SafeArrayGetElement(pArray, &myVirIndex, &wVal)) ) { err = ISAMGet_VT_I4(wVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); wStatus = NO_ISAM_ERR; if (err == ERR_INSUFF_BUFFER) wStatus = ISAM_TRUNCATION; if (err == ISAM_ERROR) wStatus = ISAM_ERROR; } } } else if (wDSDT == WBEM_DSDT_UINT32_ARRAY) { ULONG lValue = 0; cbPrecision = ULONG_PRECISION; if (myVirIndex == -1) { //String display for all elements wStatus = ISAMGetArrayInfo (vVariantVal, lValue, rgbValue, cbValueMax, pcbValue, fIsBinaryOutput, wDSDT, cbPrecision, myVirIndex); } else { //others SAFEARRAY FAR* pArray = vVariantVal.parray; if ( SUCCEEDED(SafeArrayGetElement(pArray, &myVirIndex, &lValue)) ) { err = ISAMGet_VT_I4(lValue, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); wStatus = NO_ISAM_ERR; if (err == ERR_INSUFF_BUFFER) wStatus = ISAM_TRUNCATION; if (err == ISAM_ERROR) wStatus = ISAM_ERROR; } } } else { //SINT32 long lValue = 0; cbPrecision = ULONG_PRECISION + 1; if (myVirIndex == -1) { //String display for all elements wStatus = ISAMGetArrayInfo (vVariantVal, lValue, rgbValue, cbValueMax, pcbValue, fIsBinaryOutput, wDSDT, cbPrecision, myVirIndex); } else { //others SAFEARRAY FAR* pArray = vVariantVal.parray; if ( SUCCEEDED(SafeArrayGetElement(pArray, &myVirIndex, &lValue)) ) { err = ISAMGet_VT_I4(lValue, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); wStatus = NO_ISAM_ERR; if (err == ERR_INSUFF_BUFFER) wStatus = ISAM_TRUNCATION; if (err == ISAM_ERROR) wStatus = ISAM_ERROR; } } } } else if ((varType1 == (VT_ARRAY|VT_BOOL))) { BOOL fBoolVal = TRUE; wDSDT = WBEM_DSDT_BOOL_ARRAY; cbPrecision = 1; if (myVirIndex == -1) { //String display for all elements wStatus = ISAMGetArrayInfo (vVariantVal, fBoolVal, rgbValue, cbValueMax, pcbValue, fIsBinaryOutput, wDSDT, cbPrecision, myVirIndex); } else { //others SAFEARRAY FAR* pArray = vVariantVal.parray; if ( SUCCEEDED(SafeArrayGetElement(pArray, &myVirIndex, &fBoolVal)) ) { err = ISAMGet_VT_BOOL((VARIANT_BOOL) fBoolVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); wStatus = NO_ISAM_ERR; if (err == ERR_INSUFF_BUFFER) wStatus = ISAM_TRUNCATION; if (err == ISAM_ERROR) wStatus = ISAM_ERROR; } } } else if ((varType1 == (VT_ARRAY|VT_I2))) { short wVal = 0; //If no WBEM variant type specified use default if (!wbemVariantType) wbemVariantType = WBEM_VARIANT_VT_ARRAY_I2; ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); //Get the precision for a single item in array if (wDSDT == WBEM_DSDT_SINT8_ARRAY) { //char bVal = 0; short bVal = 0; cbPrecision = UTINYINT_PRECISION + 1; if (myVirIndex == -1) { //String display for all elements wStatus = ISAMGetArrayInfo (vVariantVal, bVal, rgbValue, cbValueMax, pcbValue, fIsBinaryOutput, wDSDT, cbPrecision, myVirIndex); } else { //others SAFEARRAY FAR* pArray = vVariantVal.parray; if ( SUCCEEDED(SafeArrayGetElement(pArray, &myVirIndex, &bVal)) ) { err = ISAMGet_VT_I2(bVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); wStatus = NO_ISAM_ERR; if (err == ERR_INSUFF_BUFFER) wStatus = ISAM_TRUNCATION; if (err == ISAM_ERROR) wStatus = ISAM_ERROR; } } } else if (wDSDT == WBEM_DSDT_SINT16_ARRAY) { short wVal = 0; cbPrecision = SMALLINT_PRECISION + 1; if (myVirIndex == -1) { //String display for all elements wStatus = ISAMGetArrayInfo (vVariantVal, wVal, rgbValue, cbValueMax, pcbValue, fIsBinaryOutput, wDSDT, cbPrecision, myVirIndex); } else { //others SAFEARRAY FAR* pArray = vVariantVal.parray; if ( SUCCEEDED(SafeArrayGetElement(pArray, &myVirIndex, &wVal)) ) { err = ISAMGet_VT_I2(wVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); wStatus = NO_ISAM_ERR; if (err == ERR_INSUFF_BUFFER) wStatus = ISAM_TRUNCATION; if (err == ISAM_ERROR) wStatus = ISAM_ERROR; } } } } else if ((varType1 == (VT_ARRAY|VT_R4))) { float fltVal = (float)0.0; //If no WBEM variant type specified use default if (!wbemVariantType) wbemVariantType = WBEM_VARIANT_VT_ARRAY_R4; ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); if (myVirIndex == -1) { //String display for all elements wStatus = ISAMGetArrayInfo (vVariantVal, fltVal, rgbValue, cbValueMax, pcbValue, fIsBinaryOutput, wDSDT, cbPrecision, myVirIndex); } else { //others SAFEARRAY FAR* pArray = vVariantVal.parray; if ( SUCCEEDED(SafeArrayGetElement(pArray, &myVirIndex, &fltVal)) ) { err = ISAMGet_VT_R4(fltVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); wStatus = NO_ISAM_ERR; if (err == ERR_INSUFF_BUFFER) wStatus = ISAM_TRUNCATION; if (err == ISAM_ERROR) wStatus = ISAM_ERROR; } } } else if ((varType1 == (VT_ARRAY|VT_R8))) { double dblVal = 0; //If no WBEM variant type specified use default if (!wbemVariantType) wbemVariantType = WBEM_VARIANT_VT_ARRAY_R8; ISAMGetDataSourceDependantTypeInfo ((SWORD)wbemVariantType, syntaxStr, maxLenVal, wDSDT, dummy1, cbPrecision); if (myVirIndex == -1) { //String display for all elements wStatus = ISAMGetArrayInfo (vVariantVal, dblVal, rgbValue, cbValueMax, pcbValue, fIsBinaryOutput, wDSDT, cbPrecision, myVirIndex); } else { //others SAFEARRAY FAR* pArray = vVariantVal.parray; if ( SUCCEEDED(SafeArrayGetElement(pArray, &myVirIndex, &dblVal)) ) { err = ISAMGet_VT_R8(dblVal, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); wStatus = NO_ISAM_ERR; if (err == ERR_INSUFF_BUFFER) wStatus = ISAM_TRUNCATION; if (err == ISAM_ERROR) wStatus = ISAM_ERROR; } } } else if ((varType1 == (VT_ARRAY|VT_BSTR))) { if (myVirIndex == -1) { //String display for all elements wStatus = ISAMGetArrayStringInfo (vVariantVal, syntaxStr, rgbValue, cbValueMax, pcbValue, fIsBinaryOutput, myVirIndex); } else { //others BSTR pString = NULL; SAFEARRAY FAR* pArray = vVariantVal.parray; if ( SUCCEEDED(SafeArrayGetElement(pArray, &myVirIndex, &pString)) ) { err = ISAMGet_VT_BSTR(pString, fCType, rgbValue, cbValueMax, pcbValue, wbemVariantType, syntaxStr, maxLenVal ); wStatus = NO_ISAM_ERR; if (err == ERR_INSUFF_BUFFER) wStatus = ISAM_TRUNCATION; if (err == ISAM_ERROR) wStatus = ISAM_ERROR; //SAI ADDED SysFreeString(pString); } } if (wStatus == NO_ISAM_ERR) { //Null terminate this string if (cbValueMax > *pcbValue) { ((char*)rgbValue)[*pcbValue] = '\0'; // ODBCTRACE (_T("Null terminating this string")); } else { // ODBCTRACE (_T("Not Null terminating this string")); } } } if (wStatus == ISAM_TRUNCATION) { //Truncated data return ISAM_TRUNCATION; } else if (wStatus != NO_ISAM_ERR) { //No convertion available return wStatus; } } break; } return err; } /***************************************************************************/ // Checked for SetInterfaceSecurityEx on IWbemServices and IEnumWbemClassObject IMPLEMENT_SERIAL (CNamespace, CObject, 1) SWORD INTFUNC ISAMGetNestedNamespaces (char *parentName, char *namespaceName, IWbemServices *pGatewayIn, DWORD dwAuthLevelIn, DWORD dwImpLevelIn, char *servername, // WBEM_LOGIN_AUTHENTICATION loginMethod, char *username, char *password, BOOL fIntpretEmptPwdAsBlank, char* locale, char* authority, CMapStringToOb* map, BOOL bDeep) { // Always want to return absolute names here char *absName = NULL; IWbemServicesPtr pGateway; DWORD dwAuthLevel = 0; DWORD dwImpLevel = 0; COAUTHIDENTITY* pAuthIdent = NULL; if (NULL == pGatewayIn) { pGateway = NULL; ISAMGetGatewayServer (pGateway, (LPUSTR)servername, // loginMethod, (LPUSTR)namespaceName, (LPUSTR)username, (LPUSTR)password, (LPUSTR)locale, (LPUSTR)authority, dwAuthLevel, dwImpLevel, fIntpretEmptPwdAsBlank , &pAuthIdent); if (pGateway == NULL) return ISAM_ERROR; // the passed in name is absolute absName = new char [strlen (namespaceName) +1]; absName[0] = 0; strcpy (absName, namespaceName); map->SetAt (absName, new CNamespace (absName)); // add self } else { pGateway = pGatewayIn; pGateway->AddRef (); dwAuthLevel = dwAuthLevelIn; dwImpLevel = dwImpLevelIn; // the passed in name is relative - so build absolute - and add to map absName = new char [strlen (parentName) + strlen(namespaceName) + 2 + 1 /* for separator */]; absName[0] = 0; strcpy (absName, parentName); strcat (absName, "\\"); // add separator strcat (absName, namespaceName); map->SetAt (absName, new CNamespace (absName)); } if (!bDeep) { delete absName; return NO_ISAM_ERR; } //cloaking BOOL fIsLocalConnection = IsLocalServer(servername); if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(pGateway, dwAuthLevel, dwImpLevel); } //Enumerate children and recurse IEnumWbemClassObject* pNamespaceEnum = NULL; BSTR nspaceBSTR = SysAllocString(WBEMDR32_L_NAMESPACE); IWbemContext* pContext = ISAMCreateLocaleIDContextObject(locale); if ( FAILED(pGateway->CreateInstanceEnum(nspaceBSTR, 0, pContext, &pNamespaceEnum)) ) { delete absName; SysFreeString(nspaceBSTR); if (pContext) pContext->Release(); //Should be not also Release pGateway ? return NO_ISAM_ERR; } else { ISAMSetCloaking2(pNamespaceEnum, fIsLocalConnection, IsW2KOrMore(), dwAuthLevel, dwImpLevel, pAuthIdent); /* if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(pNamespaceEnum, dwAuthLevel, dwImpLevel); } else { //Set Dcom blanket SetInterfaceSecurityEx(pNamespaceEnum, pAuthIdent, gpPrincipal, dwAuthLevel, dwImpLevel); } */ SysFreeString(nspaceBSTR); if (pContext) pContext->Release(); if (!pNamespaceEnum) { delete absName; return NO_ISAM_ERR; } ULONG uRet = 0; IWbemClassObject* pNewInst = NULL; pNamespaceEnum->Reset(); while ( S_OK == pNamespaceEnum->Next(-1, 1, &pNewInst, &uRet) ) { VARIANTARG var; //SAI ADDED no need to init VariantInit (&var); BSTR nameBSTR = SysAllocString(WBEMDR32_L_NAME); pNewInst->Get(nameBSTR, 0, &var, NULL, NULL); SysFreeString(nameBSTR); IWbemServicesPtr pNewGateway = NULL; COAUTHIDENTITY* pNewAuthIdent = NULL; //Get user and password fields #ifdef USING_ABSPATH char testBuff [MAX_QUALIFIER_NAME_LENGTH + 1]; testBuff[0] = 0; wcstombs(testBuff, var.bstrVal, MAX_QUALIFIER_NAME_LENGTH); testBuff[MAX_QUALIFIER_NAME_LENGTH] = 0; char* cTemp2 = new char [strlen (absName) + strlen(testBuff) + 2]; cTemp2[0] = 0; lstrcpy(cTemp2,absName); lstrcat(cTemp2, "\\"); lstrcat(cTemp2,testBuff); ISAMGetGatewayServer (pNewGateway, servername, // loginMethod, cTemp2, username, password, locale, authority, &pNewAuthIdent); delete cTemp2; if (pNewGateway) #else BSTR myRelativeNamespace = var.bstrVal; CBString cbNS (myRelativeNamespace, FALSE); IWbemContext* mycontext = ISAMCreateLocaleIDContextObject(locale); if ( SUCCEEDED(pGateway->OpenNamespace(cbNS.GetString(), 0, mycontext, &pNewGateway, NULL)) ) #endif { BOOL fIsLocalConnection = IsLocalServer(servername); ISAMSetCloaking2(pNewGateway, fIsLocalConnection, IsW2KOrMore(), dwAuthLevel, dwImpLevel, pNewAuthIdent); /* if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(pNewGateway, dwAuthLevel, dwImpLevel); } else { //Set Dcom blanket SetInterfaceSecurityEx(pNewGateway, pNewAuthIdent, gpPrincipal, dwAuthLevel, dwImpLevel); } */ size_t len = wcstombs (NULL, var.bstrVal, MB_CUR_MAX); if (-1 != len) { char *name = new char [len + 1]; name[0] = 0; wcstombs (name, var.bstrVal, len); name [len] = 0; ISAMGetNestedNamespaces (absName, name, pNewGateway, dwAuthLevel, dwImpLevel, servername, // loginMethod, username, password, fIntpretEmptPwdAsBlank, locale, authority, map); delete name; } if (pNewAuthIdent) { WbemFreeAuthIdentity( pNewAuthIdent ); pNewAuthIdent = NULL; } } #ifndef USING_ABSPATH if (mycontext) mycontext->Release(); #endif VariantClear(&var); } //Tidy Up if (pNamespaceEnum) { pNamespaceEnum->Release(); } } delete absName; if (pAuthIdent ) { WbemFreeAuthIdentity( pAuthIdent ); pAuthIdent = NULL; } return NO_ISAM_ERR; } /***************************************************************************/ SWORD INTFUNC ISAMBuildTree (HTREEITEM hParent, char *namespaceName, //relative name CTreeCtrl& treeCtrl, CConnectionDialog& dialog, char *server, // WBEM_LOGIN_AUTHENTICATION loginMethod, char *username, char *password, BOOL fIntpretEmptPwdAsBlank, char *locale, char *authority, BOOL fNeedChildren, BOOL deep, HTREEITEM& hTreeItem) { // Note the first name in the tree will be displayed as absolute // could strip off the non- root bit - might do it ODBCTRACE ("\nWBEM ODBC Driver :ISAMBuildTree\n"); // Add self hTreeItem = dialog.InsertItem(treeCtrl, hParent, namespaceName); ODBCTRACE ("\nWBEM ODBC Driver :Add Self :"); ODBCTRACE (namespaceName); ODBCTRACE ("\n"); //Enumerate children and recurse //BUT ONLY IF REQUESTED if (fNeedChildren) { ODBCTRACE ("\nWBEM ODBC Driver : fNeedChildren = TRUE\n"); //Work out absolute name of new namespace TV_ITEM tvItem2; tvItem2.hItem = hTreeItem; tvItem2.mask = TVIF_PARAM; if (treeCtrl.GetItem (&tvItem2)) { char* txt = ((ISAMTreeItemData*)tvItem2.lParam)->absName; return ISAMBuildTreeChildren(hTreeItem, txt, treeCtrl, dialog, server, // loginMethod, username, password, fIntpretEmptPwdAsBlank,locale, authority, deep); } else { return ISAM_ERROR; } } else { ODBCTRACE ("\nWBEM ODBC Driver : fNeedChildren = FALSE\n"); } return NO_ISAM_ERR; } /***************************************************************************/ // Checked for SetInterfaceSecurityEx on IWbemServices and IEnumWbemClassObject SWORD INTFUNC ISAMBuildTreeChildren (HTREEITEM hParent, char *namespaceName, //absolute name CTreeCtrl& treeCtrl, CConnectionDialog& dialog, char *server, // WBEM_LOGIN_AUTHENTICATION loginMethod, char *username, char *password, BOOL fIntpretEmptPwdAsBlank, char *locale, char *authority, BOOL deep) { ODBCTRACE ("\nWBEM ODBC Driver : ISAMBuildTreeChildren\n"); MyImpersonator fred (username, password, authority, "ISAMBuildTreeChildren"); //Advance to the namespace for which you require the children DWORD dwAuthLevel = 0; DWORD dwImpLevel = 0; COAUTHIDENTITY* pAuthIdent = NULL; IWbemServicesPtr pGateway = NULL; ISAMGetGatewayServer (pGateway, (LPUSTR)server, // loginMethod, (LPUSTR)namespaceName, (LPUSTR)username, (LPUSTR)password, (LPUSTR)locale, (LPUSTR)authority, dwAuthLevel, dwImpLevel, fIntpretEmptPwdAsBlank, &pAuthIdent); if (pGateway == NULL) { ODBCTRACE ("\nWBEM ODBC Driver : ISAMBuildTreeChildren : Failed to get gateway server\n"); return ISAM_ERROR; } //cloaking BOOL fIsLocalConnection = IsLocalServer(server); if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(pGateway, dwAuthLevel, dwImpLevel); } //Indicate that this node has been checked for children TV_ITEM tvItem; tvItem.hItem = hParent; tvItem.mask = TVIF_PARAM; if (treeCtrl.GetItem (&tvItem)) { ((ISAMTreeItemData*)tvItem.lParam)->fExpanded = TRUE; } //Get all children namespaces by fetching instances of __NAMESPACE IEnumWbemClassObjectPtr pNamespaceEnum = NULL; BSTR nspaceBSTR = SysAllocString(WBEMDR32_L_NAMESPACE); IWbemContext* pContext = ISAMCreateLocaleIDContextObject(locale); SCODE scCI = pGateway->CreateInstanceEnum(nspaceBSTR, 0, pContext, &pNamespaceEnum); SysFreeString(nspaceBSTR); if (pContext) pContext->Release(); ISAMSetCloaking2(pNamespaceEnum, fIsLocalConnection, IsW2KOrMore(), dwAuthLevel, dwImpLevel, pAuthIdent); /* if ( fIsLocalConnection && IsW2KOrMore() ) { WbemSetDynamicCloaking(pNamespaceEnum, dwAuthLevel, dwImpLevel); } else { //Set Dcom blanket SetInterfaceSecurityEx(pNamespaceEnum, pAuthIdent, gpPrincipal, dwAuthLevel, dwImpLevel); } */ if ( FAILED(scCI) || (pNamespaceEnum == NULL) ) { return ISAM_ERROR; } ULONG uRet = 0; IWbemClassObjectPtr pNewInst = NULL; pNamespaceEnum->Reset(); while ( S_OK == pNamespaceEnum->Next(-1, 1, &pNewInst, &uRet) ) { //(14) VARIANTARG var; BSTR thenameBSTR = SysAllocString(WBEMDR32_L_NAME); pNewInst->Get(thenameBSTR, 0, &var, NULL, NULL); SysFreeString(thenameBSTR); //RAID 42256 UINT cpThread = Utility_GetCodePageFromLCID(GetThreadLocale()); int len = WideCharToMultiByte(cpThread,WC_COMPOSITECHECK, (const wchar_t*)var.bstrVal, -1, NULL, 0, NULL, NULL); if (-1 != len) { char *name = new char [len + 1]; //RAID 42256 _bstr_t myValue((BSTR)var.bstrVal); Utility_WideCharToDBCS(myValue, &name, len); name [len] = '\0'; //Check if this child already exists in tree CString fullPath = namespaceName; fullPath += "\\"; fullPath += name; HTREEITEM hDummy; if (! dialog.FindAbsName((char*)(LPCTSTR)fullPath, hParent, hDummy) ) { //Add child to tree control HTREEITEM newTreeItem = NULL; ISAMBuildTree (hParent, name, treeCtrl, dialog, server, // loginMethod, username, password, fIntpretEmptPwdAsBlank, locale, authority, deep, deep, newTreeItem); if (deep && newTreeItem) dialog.AddNamespaces(newTreeItem, FALSE); } delete name; } //Tidy Up VariantClear(&var); } if (pAuthIdent ) { WbemFreeAuthIdentity( pAuthIdent ); pAuthIdent = NULL; } return NO_ISAM_ERR; } /***************************************************************************/ // Checked for SetInterfaceSecurityEx on IWbemServices void ISAMGetIWbemServices(LPISAM lpISAM, CSafeWbemServices& mServices, IWbemServicesPtr& myServicesPtr) { myServicesPtr = NULL; mServices.GetInterfacePtr(myServicesPtr); ISAMPatchUpGatewaySecurity(lpISAM, myServicesPtr); } void CSafeWbemServices::Transfer(CSafeWbemServices& original) { m_pStream = original.m_pStream; original.m_pStream = NULL; m_params = original.m_params; original.m_params = NULL; m_fValid = original.m_fValid; original.m_fValid = FALSE; } HRESULT CSafeWbemServices::GetInterfacePtr(IWbemServicesPtr& pServices) { bool bRet = false; if(m_pStream) { HRESULT hr; //pop Com pointer out from stream //as you are popping into &SmartPointer so increase in ref count hr = CoGetInterfaceAndReleaseStream(m_pStream,IID_IWbemServices,(void**)&pServices); m_pStream = NULL; if (m_params) m_params->m_myStream = NULL; bRet = true; if ( SUCCEEDED(hr) ) { //push value back into stream //as you are CoMarshalling into stream ref count bumped up by one hr = CoMarshalInterThreadInterfaceInStream(IID_IWbemServices,pServices,&m_pStream); if (m_params) m_params->m_myStream = m_pStream; } } return S_OK; } // Checked for SetInterfaceSecurityEx on IWbemServices void CSafeWbemServices::SetInterfacePtr(LPISAM lpISAM, LPUSTR lpQualifierName, SWORD cbQualifierName) { ODBCTRACE("\nWBEM ODBC Driver :CSafeWbemServices::SetInterfacePtr\n"); // //Create interface on Working Thread // //Create parameter set so that an equivalent one can be created //on the working thread. (never used but must exist) if (m_params) { BOOL status = PostSuspensiveThreadMessage(glob_myWorkerThread.GetThreadId(), MYUSRMESS_REMOVE_SERVICES, 0, (LPARAM)m_params); m_pStream = NULL; delete m_params; m_params = NULL; } m_params = new MyWorkingThreadParams(lpISAM, lpQualifierName, cbQualifierName, m_pStream); //post message to create this object on working thread ODBCTRACE("\nWBEM ODBC Driver :CSafeWbemServices::SetInterfacePtr : pos 1\n"); BOOL status = PostSuspensiveThreadMessage(glob_myWorkerThread.GetThreadId(), MYUSRMESS_CREATE_SERVICES, 0, (LPARAM)m_params); ODBCTRACE("\nWBEM ODBC Driver :CSafeWbemServices::SetInterfacePtr : pos 2\n"); m_fValid = ( SUCCEEDED(m_params->sc) ) ? TRUE : FALSE; m_pStream = m_params->m_myStream; } CSafeWbemServices::CSafeWbemServices() { m_params = NULL; m_fValid = FALSE; m_pStream = NULL; } CSafeWbemServices::~CSafeWbemServices() { //clean up working thread parameters //and IWbemServices object on working thread if (m_params) { BOOL status = PostSuspensiveThreadMessage(glob_myWorkerThread.GetThreadId(), MYUSRMESS_REMOVE_SERVICES, 0, (LPARAM)m_params); m_pStream = NULL; delete m_params; m_params = NULL; } } void CSafeWbemServices::Invalidate() { if (m_params) { BOOL status = PostSuspensiveThreadMessage(glob_myWorkerThread.GetThreadId(), MYUSRMESS_REMOVE_SERVICES, 0, (LPARAM)m_params); m_pStream = NULL; delete m_params; m_params = NULL; } m_fValid = FALSE; m_pStream = NULL; } BOOL CSafeWbemServices::PostSuspensiveThreadMessage(DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam) { BOOL status = FALSE; ODBCTRACE("\nWBEM ODBC Driver : CSafeWbemServices::PostSuspensiveThreadMessage\n"); EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); ODBCTRACE("\nWBEM ODBC Driver : CSafeWbemServices::PostSuspensiveThreadMessage : in critical section\n"); //check data in lParam MyWorkingThreadParams* myData = (MyWorkingThreadParams*)lParam; //Extract Event Handle HANDLE EventHnd = myData->m_EventHnd; //make sure the event is in its non-signaled state //before posting the thread message ResetEvent(EventHnd); ODBCTRACE("\nWBEM ODBC Driver : CSafeWbemServices::PostSuspensiveThreadMessage: about to leave critical section\n"); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); //post message ODBCTRACE("\nWBEM ODBC Driver : CSafeWbemServices::PostSuspensiveThreadMessage: PostThreadMessage\n"); status = PostThreadMessage(idThread, Msg, wParam, lParam); if (!status) { ODBCTRACE("\nWBEM ODBC Driver : CSafeWbemServices::PostSuspensiveThreadMessage: PostThreadMessage failed\n"); } //Make it suspensive WaitForSingleObject(EventHnd, INFINITE); ODBCTRACE("\nWBEM ODBC Driver : CSafeWbemServices::PostSuspensiveThreadMessage : After wait for single object\n"); return status; } // Checked for SetInterfaceSecurityEx on IWbemServices LONG OnUserCreateServices(UINT wParam, LONG lParam) { ODBCTRACE("\n\n*****WBEM ODBC Driver : OnUserCreateServices*****\n\n"); COleInitializationManager oleManager; EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); ODBCTRACE("\nWBEM ODBC Driver : OnUserCreateServices : entered critial section\n"); //this is done on the worker thread //check data in lParam MyWorkingThreadParams* myData = (MyWorkingThreadParams*)lParam; //Tidy up existing stream if(myData->m_myStream) { //pop interface into smart pointer. //As it goes into &SmartPointer ref count stays the same IWbemServicesPtr tempy; HRESULT hr = CoGetInterfaceAndReleaseStream(myData->m_myStream, IID_IWbemServices, (void**)&tempy); //when SmartPointer goes out of scope it will call Release and free up interface cleanly } myData->m_myStream = NULL; //Setup impersonation on working thread MyImpersonator im (myData->m_lpISAM, "Worker Thread:CreateServices"); //now add IWbemServices IWbemServicesPtr tempy = NULL; ISAMGetGatewayServer(tempy, myData->m_lpISAM, myData->m_lpQualifierName, myData->m_cbQualifierName); myData->pGateway = tempy.Detach(); // CBString myServerStr; // myServerStr.AddString( (LPSTR)myData->m_lpISAM->szServer, FALSE ); // CServerLocationCheck myCheck (myServerStr); BOOL fIsLocalConnection = myData->m_lpISAM->fIsLocalConnection;//myCheck.IsLocal(); if ( fIsLocalConnection && (myData->m_lpISAM->fW2KOrMore) ) { WbemSetDynamicCloaking(myData->pGateway, myData->m_lpISAM->dwAuthLevel, myData->m_lpISAM->dwImpLevel); } if (myData->pGateway) { HRESULT hr; ODBCTRACE("\nWBEM ODBC Driver OnUserCreateServices : succeeded to create IWbemServices on working thread\n"); //push Com pointer in stream //The CoMarshalling will bump up ref count by one if (SUCCEEDED(hr = CoMarshalInterThreadInterfaceInStream(IID_IWbemServices, myData->pGateway, &(myData->m_myStream)))) { // //Created services pointer now to be marshalled in stream myData->sc = WBEM_S_NO_ERROR; } else myData->sc = hr; } else { myData->sc = WBEM_E_FAILED; ODBCTRACE("\nWBEM ODBC Driver OnUserCreateServices : failed to create IWbemServices on working thread\n"); } //so that WaitForSingleObject returns SetEvent(myData->m_EventHnd); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); ODBCTRACE("\nWBEM ODBC Driver : OnUserCreateServices : left critial section\n"); return 0; } LONG OnUserRemoveServices(UINT wParam, LONG lParam) { ODBCTRACE("\n\n*****WBEM ODBC Driver : OnUserRemoveServices*****\n\n"); COleInitializationManager oleManager; EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); ODBCTRACE("\nWBEM ODBC Driver : OnUserRemoveServices : entered crital section\n"); //this is done on the worker thread //check data in lParam MyWorkingThreadParams* myData = (MyWorkingThreadParams*)lParam; ODBCTRACE("\nWBEM ODBC Driver : OnUserRemoveServices : about to Release IWbemServices\n"); //Remove the interface form the stream if(myData->m_myStream) { //the release should pop any Com pointers out from stream //the use of smart pointers should call Release to free up // the Com pointer IWbemServicesPtr tempy = NULL; HRESULT hr = CoGetInterfaceAndReleaseStream(myData->m_myStream, IID_IWbemServices, (void**)&tempy); myData->m_myStream = NULL; } if (myData->pGateway) { //remove the IWbemServices pointer from worker thread myData->pGateway->Release(); myData->pGateway = NULL; } //so that WaitForSingleObject returns SetEvent(myData->m_EventHnd); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); ODBCTRACE("\nWBEM ODBC Driver : OnUserRemoveServices : left critial section\n"); return 0; } LONG OnUserCreateEnum(UINT wParam, LONG lParam) { ODBCTRACE("\n\n*****WBEM ODBC Driver : OnUserCreateEnum*****\n\n"); COleInitializationManager oleManager; EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); ODBCTRACE("\nWBEM ODBC Driver : OnUserCreateEnum : entered critial section\n"); //this is done on the worker thread //check data in lParam MyWorkingThreadParams* myData = (MyWorkingThreadParams*)lParam; //now add IEnumWbemClassObject //first check if you need to ExecQuery or CreateInstanceEnum //remember to return scode in myData if(myData->m_myStream) { //the release should pop any Com pointers out from stream //the use of smart pointers should call Release to free up // the Com pointer IEnumWbemClassObjectPtr tempy = NULL; HRESULT hr = CoGetInterfaceAndReleaseStream(myData->m_myStream, IID_IEnumWbemClassObject, (void**)&tempy); } myData->m_myStream = NULL; //Create tempory context object IWbemContext* pContext = ISAMCreateLocaleIDContextObject(myData->m_lpISAM->m_Locale); //Setup impersonation on working thread MyImpersonator im (myData->m_lpISAM, "Worker Thread"); IWbemServicesPtr myServicesPtr = NULL; ISAMGetIWbemServices(myData->m_lpISAM, *(myData->pServ), myServicesPtr); // CBString myServerStr; // myServerStr.AddString( (LPSTR)myData->m_lpISAM->szServer, FALSE ); // CServerLocationCheck myCheck (myServerStr); BOOL fIsLocalConnection = myData->m_lpISAM->fIsLocalConnection;//myCheck.IsLocal(); if ( fIsLocalConnection && (myData->m_lpISAM->fW2KOrMore) ) { WbemSetDynamicCloaking(myServicesPtr, myData->m_lpISAM->dwAuthLevel, myData->m_lpISAM->dwImpLevel); } DWORD dwSize; char buffer[1001]; buffer[0] = 0; GetUserName(buffer, &dwSize); CString lpMessage; lpMessage.Format("\nUser Account just before Enum or ExecQuery : %s\n", buffer); ODBCTRACE(lpMessage); if ( (myData->fIsExecQuery) == WMI_CREATE_INST_ENUM ) { //CreateInstanceEnum myData->sc = myServicesPtr->CreateInstanceEnum(myData->tableName, 0, pContext, &(myData->pEnum)); } else { //ExecQuery long flags = 0; if ( (myData->fIsExecQuery) == WMI_EXEC_FWD_ONLY ) flags = WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY; else if ( (myData->fIsExecQuery) == WMI_PROTOTYPE ) flags = WBEM_FLAG_PROTOTYPE; BSTR wqlBSTR = SysAllocString(WBEMDR32_L_WQL); myData->sc = myServicesPtr->ExecQuery(wqlBSTR, myData->sqltextBSTR, flags, pContext, &(myData->pEnum)); SysFreeString(wqlBSTR); } //Tidy up if (pContext) pContext->Release(); if ( SUCCEEDED(myData->sc) ) { ODBCTRACE("\nWBEM ODBC Driver OnUserCreateEnum : succeeded to create IEnumWbemClassObject on working thread\n"); if (myData->pEnum) { //push Com pointer in stream //The CoMarshalling will bump the ref count up by one if (FAILED( CoMarshalInterThreadInterfaceInStream(IID_IEnumWbemClassObject, myData->pEnum, &(myData->m_myStream)))) { ODBCTRACE("\nWBEM ODBC Driver OnUserCreateEnum : failed to CoMarshalInterThreadInterfaceInStream\n"); } } } else { ODBCTRACE("\nWBEM ODBC Driver OnUserCreateEnum : failed to create IEnumWbemClassObject on working thread\n"); } //so that WaitForSingleObject returns SetEvent(myData->m_EventHnd); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); ODBCTRACE("\nWBEM ODBC Driver : OnUserCreateEnum : left critial section\n"); return 0; } LONG OnUserRemoveEnum(UINT wParam, LONG lParam) { ODBCTRACE("\n\n*****WBEM ODBC Driver : OnUserRemoveEnum*****\n\n"); COleInitializationManager oleManager; EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); ODBCTRACE("\nWBEM ODBC Driver : OnUserRemoveEnum : entered crital section\n"); //this is done on the worker thread //check data in lParam MyWorkingThreadParams* myData = (MyWorkingThreadParams*)lParam; ODBCTRACE("\nWBEM ODBC Driver : OnUserRemoveEnum : about to Release IEnumWbemClassObject\n"); if(myData->m_myStream) { //the release should pop any Com pointers out from stream //the use of smart pointers should call Release to free up // the Com pointer IEnumWbemClassObjectPtr tempy = NULL; HRESULT hr = CoGetInterfaceAndReleaseStream(myData->m_myStream, IID_IEnumWbemClassObject, (void**)&tempy); } myData->m_myStream = NULL; if (myData->pEnum) { //remove the IWbemServices pointer from worker thread myData->pEnum->Release(); myData->pEnum = NULL; } //so that WaitForSingleObject returns SetEvent(myData->m_EventHnd); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); ODBCTRACE("\nWBEM ODBC Driver : OnUserRemoveEnum : left critial section\n"); return 0; } void OnIncreamentRefCount(UINT wParam, LONG lParam) { EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); ++glob_myWorkerThread.m_cRef; CString message; message.Format ("\n***** Working thread count (increment) = %ld *****\n", glob_myWorkerThread.m_cRef); ODBCTRACE(message); //check data in lParam MyWorkingThreadParams* myData = (MyWorkingThreadParams*)lParam; //so that WaitForSingleObject returns SetEvent(myData->m_EventHnd); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); } void OnDecreamentRefCount(UINT wParam, LONG lParam) { EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); if (glob_myWorkerThread.m_cRef) { --glob_myWorkerThread.m_cRef; CString message; message.Format ("\n***** Working thread count (descrement) = %ld *****\n", glob_myWorkerThread.m_cRef); ODBCTRACE(message); } //check data in lParam MyWorkingThreadParams* myData = (MyWorkingThreadParams*)lParam; //so that WaitForSingleObject returns SetEvent(myData->m_EventHnd); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); } //DWORD WINAPI MyWorkerThread(LPVOID myVal) unsigned __stdcall MyWorkerThread(LPVOID myVal) { //this is done on the worker thread DWORD dwThreadId = GetCurrentThreadId(); //force a thread message queue to be created MSG msg; PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); //so that WaitForSingleObject returns //infinate loop for thread to read messages BOOL status = FALSE; BOOL myLoop = TRUE; while (myLoop) { //look for messages in the range WM_USER, MYUSRMESS_REMOVE_ENUM status = PeekMessage(&msg, NULL, WM_USER, MYUSRMESS_REMOVE_ENUM, PM_NOREMOVE); if (status) { switch (msg.message) { case MYUSRMESS_CREATE_SERVICES: { ODBCTRACE("\nWBEM ODBC Driver : MyWorkerThread : MYUSRMESS_CREATE_SERVICES\n"); PeekMessage(&msg, NULL, MYUSRMESS_CREATE_SERVICES, MYUSRMESS_CREATE_SERVICES, PM_REMOVE); OnUserCreateServices(msg.wParam, msg.lParam); } break; case MYUSRMESS_REMOVE_SERVICES: { ODBCTRACE("\nWBEM ODBC Driver : MyWorkerThread : MYUSRMESS_REMOVE_SERVICES\n"); PeekMessage(&msg, NULL, MYUSRMESS_REMOVE_SERVICES, MYUSRMESS_REMOVE_SERVICES, PM_REMOVE); OnUserRemoveServices(msg.wParam, msg.lParam); } break; case MYUSRMESS_CLOSE_WKERTHRED: { ODBCTRACE("\nWBEM ODBC Driver : MyWorkerThread : MYUSRMESS_CLOSE_WKERTHRED\n"); PeekMessage(&msg, NULL, MYUSRMESS_CLOSE_WKERTHRED, MYUSRMESS_CLOSE_WKERTHRED, PM_REMOVE); ISAMCloseWorkerThread2(msg.wParam, msg.lParam); myLoop = FALSE; //need to exit thread when ISAMCloseWorkerThread2 exists } break; case MYUSRMESS_REFCOUNT_INCR: { ODBCTRACE("\nWBEM ODBC Driver : MyWorkerThread : MYUSRMESS_REFCOUNT_INCR\n"); PeekMessage(&msg, NULL, MYUSRMESS_REFCOUNT_INCR, MYUSRMESS_REFCOUNT_INCR, PM_REMOVE); OnIncreamentRefCount(msg.wParam, msg.lParam); } break; case MYUSRMESS_REFCOUNT_DECR: { ODBCTRACE("\nWBEM ODBC Driver : MyWorkerThread : MYUSRMESS_REFCOUNT_DECR\n"); PeekMessage(&msg, NULL, MYUSRMESS_REFCOUNT_DECR, MYUSRMESS_REFCOUNT_DECR, PM_REMOVE); OnDecreamentRefCount(msg.wParam, msg.lParam); } break; case MYUSRMESS_CREATE_ENUM: { ODBCTRACE("\nWBEM ODBC Driver : MyWorkerThread : MYUSRMESS_CREATE_ENUM\n"); PeekMessage(&msg, NULL, MYUSRMESS_CREATE_ENUM, MYUSRMESS_CREATE_ENUM, PM_REMOVE); OnUserCreateEnum(msg.wParam, msg.lParam); } break; case MYUSRMESS_REMOVE_ENUM: { ODBCTRACE("\nWBEM ODBC Driver : MyWorkerThread : MYUSRMESS_REMOVE_ENUM\n"); PeekMessage(&msg, NULL, MYUSRMESS_REMOVE_ENUM, MYUSRMESS_REMOVE_ENUM, PM_REMOVE); OnUserRemoveEnum(msg.wParam, msg.lParam); } break; default: { CString myMessage; myMessage.Format("\nWBEM ODBC Driver : MyWorkerThread : unknown message %ld which I will remove off the thread queue\n", msg.message); ODBCTRACE(myMessage); PeekMessage(&msg, NULL, msg.message, msg.message, PM_REMOVE); } break; } } Sleep(10); } //The thread will exit here return 500; } CWorkerThreadManager::CWorkerThreadManager() { fIsValid = FALSE; //initalize critical section for shared data InitializeCriticalSection(&m_cs); dwThreadId = 0; m_cRef = 0; hr = NULL; } void CWorkerThreadManager::CreateWorkerThread() { //Create a worker thread EnterCriticalSection(& m_cs ); dwThreadId = 0; m_cRef = 1; //sets the ref count to 1 hr = (HANDLE)_beginthreadex(NULL, 0, &MyWorkerThread, NULL, 0, (unsigned int*)&dwThreadId); fIsValid = TRUE; LeaveCriticalSection(& m_cs ); } void CWorkerThreadManager::Invalidate() { //only called after working thread is exited dwThreadId = 0; hr = NULL; fIsValid = FALSE; m_cRef = 0; } void ISAMCloseWorkerThread1() { ODBCTRACE("\n\n***** ISAMCloseWorkerThread1 *****\n\n"); MyWorkingThreadParams* m_params = new MyWorkingThreadParams(NULL, NULL, 0, NULL); EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); HANDLE EventHnd = m_params->m_EventHnd; ResetEvent(EventHnd); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); PostThreadMessage(glob_myWorkerThread.GetThreadId(), MYUSRMESS_CLOSE_WKERTHRED, 0, (LPARAM)m_params); //Wait on termination of thread WaitForSingleObject(glob_myWorkerThread.GetThreadHandle(), INFINITE); delete m_params; } CWorkerThreadManager::~CWorkerThreadManager() { //close thread ODBCTRACE("\n\n***** Shutting down worker thread *****\n\n"); //close critical section DeleteCriticalSection(&m_cs); } void ISAMCloseWorkerThread2(UINT wParam, LONG lParam) { //this is done on the worker thread ODBCTRACE("\n\n***** ISAMCloseWorkerThread2 *****\n\n"); EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); //this is done on the worker thread //check data in lParam MyWorkingThreadParams* myData = (MyWorkingThreadParams*)lParam; //so that WaitForSingleObject returns //so ISAMCloseWorkerThread1 can continue and Invalidate the //global worker thread SetEvent(myData->m_EventHnd); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); //when you exit this method and return to 'MyWorkerThread' //it will exit the loop and thus automatically terminate the thread } MyWorkingThreadParams::MyWorkingThreadParams(LPISAM lpISAM, LPUSTR lpQualifierName, SWORD cbQualifierName, IStream* myStream) { //This will be created on worker thread m_lpISAM = lpISAM; m_lpQualifierName = lpQualifierName; m_cbQualifierName = cbQualifierName; m_myStream = myStream; pGateway = NULL; //will be filled in later pEnum = NULL; //Create an event object //so that message to worker thread can be suspensive m_EventHnd = CreateEvent(NULL, TRUE, FALSE, NULL); } MyWorkingThreadParams::MyWorkingThreadParams(LPISAM lpISAM, WmiEnumTypes a_fIsExecQuery, BSTR theBstrValue, CSafeWbemServices* a_pServ, IStream* myStream) { //This will be created on worker thread m_lpISAM = lpISAM; fIsExecQuery = a_fIsExecQuery; sqltextBSTR = NULL; tableName = NULL; if (a_fIsExecQuery != WMI_CREATE_INST_ENUM) { sqltextBSTR = theBstrValue; } else { tableName = theBstrValue; } pServ = a_pServ; m_myStream = myStream; pGateway = NULL; pEnum = NULL; //will be filled in later sc = 0; //Create an event object //so that message to worker thread can be suspensive m_EventHnd = CreateEvent(NULL, TRUE, FALSE, NULL); } MyWorkingThreadParams::~MyWorkingThreadParams() { //This will be cleaned up on worker thread if (m_EventHnd) { CloseHandle(m_EventHnd); } if (pGateway) { ODBCTRACE("\nShould never get here, deleting Gateway\n"); } if (pEnum) { ODBCTRACE("\nShould never get here, deleting Enumeration\n"); } } COleInitializationManager::COleInitializationManager() { //Initialize Ole OleInitialize(0); } COleInitializationManager::~COleInitializationManager() { //Uninitialize OLE OleUninitialize(); } CSafeIEnumWbemClassObject::CSafeIEnumWbemClassObject() { m_fValid = FALSE; m_pStream = NULL; m_params = NULL; } CSafeIEnumWbemClassObject::~CSafeIEnumWbemClassObject() { if (m_params) { BOOL status = PostSuspensiveThreadMessage(glob_myWorkerThread.GetThreadId(), MYUSRMESS_REMOVE_ENUM, 0, (LPARAM)m_params); m_pStream = NULL; delete m_params; m_params = NULL; } } BOOL CSafeIEnumWbemClassObject::PostSuspensiveThreadMessage(DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam) { BOOL status = FALSE; ODBCTRACE("\nWBEM ODBC Driver : CSafeIEnumWbemClassObject::PostSuspensiveThreadMessage\n"); EnterCriticalSection(& (glob_myWorkerThread.m_cs) ); ODBCTRACE("\nWBEM ODBC Driver : CSafeIEnumWbemClassObject::PostSuspensiveThreadMessage : in critical section\n"); //check data in lParam MyWorkingThreadParams* myData = (MyWorkingThreadParams*)lParam; //Extract Event Handle HANDLE EventHnd = myData->m_EventHnd; //make sure the event is in its non-signaled state //before posting the thread message ResetEvent(EventHnd); ODBCTRACE("\nWBEM ODBC Driver : CSafeIEnumWbemClassObject::PostSuspensiveThreadMessage: about to leave critical section\n"); LeaveCriticalSection(& (glob_myWorkerThread.m_cs) ); //post message ODBCTRACE("\nWBEM ODBC Driver : CSafeIEnumWbemClassObject::PostSuspensiveThreadMessage: PostThreadMessage\n"); status = PostThreadMessage(idThread, Msg, wParam, lParam); if (!status) { ODBCTRACE("\nWBEM ODBC Driver : CSafeWbemServices::PostSuspensiveThreadMessage: PostThreadMessage failed\n"); } //Make it suspensive WaitForSingleObject(EventHnd, INFINITE); ODBCTRACE("\nWBEM ODBC Driver : CSafeIEnumWbemClassObject::PostSuspensiveThreadMessage : After wait for single object\n"); return status; } HRESULT CSafeIEnumWbemClassObject::GetInterfacePtr(IEnumWbemClassObjectPtr& pIEnum) { bool bRet = false; if(m_pStream) { HRESULT hr; //pop Com pointer out from stream //as we are using &SmartPointer the ref count stays the same hr = CoGetInterfaceAndReleaseStream(m_pStream,IID_IEnumWbemClassObject,(void**)&pIEnum); m_pStream = NULL; if (m_params) m_params->m_myStream = NULL; bRet = true; if ( SUCCEEDED(hr) ) { //push the interface back into stream. //As we are CoMarshalling the interface the ref count bumps up by one hr = CoMarshalInterThreadInterfaceInStream(IID_IEnumWbemClassObject,pIEnum,&m_pStream); if (m_params) m_params->m_myStream = m_pStream; } } return S_OK; } HRESULT CSafeIEnumWbemClassObject::SetInterfacePtr(LPISAM lpISAM, WmiEnumTypes fIsEXecQuery, BSTR theBstrValue, CSafeWbemServices* pServ) { //Tidy up any previous values if (m_params) { BOOL status = PostSuspensiveThreadMessage(glob_myWorkerThread.GetThreadId(), MYUSRMESS_REMOVE_ENUM, 0, (LPARAM)m_params); m_pStream = NULL; delete m_params; m_params = NULL; } //Set new value m_params = new MyWorkingThreadParams(lpISAM, fIsEXecQuery, theBstrValue, pServ, m_pStream); //post message to create this object on working thread ODBCTRACE("\nWBEM ODBC Driver :CSafeWbemServices::SetInterfacePtr : pos 1\n"); BOOL status = PostSuspensiveThreadMessage(glob_myWorkerThread.GetThreadId(), MYUSRMESS_CREATE_ENUM, 0, (LPARAM)m_params); ODBCTRACE("\nWBEM ODBC Driver :CSafeWbemServices::SetInterfacePtr : pos 2\n"); m_fValid = ( SUCCEEDED(m_params->sc) ) ? TRUE : FALSE; m_pStream = m_params->m_myStream; return (m_params->sc); } void CSafeIEnumWbemClassObject::Invalidate() { if (m_params) { BOOL status = PostSuspensiveThreadMessage(glob_myWorkerThread.GetThreadId(), MYUSRMESS_REMOVE_ENUM, 0, (LPARAM)m_params); m_pStream = NULL; delete m_params; m_params = NULL; } m_pStream = NULL; m_fValid = FALSE; } // Checked for SetInterfaceSecurityEx on IWbemServices BOOL IsLocalServer(LPSTR szServer) { //A local server could be specified as a NULL or blank string //a '.' character or a fully qualified \\MyLocalServer //we need to check each of these cases if (!szServer || !*szServer) return TRUE; // Get past the \\ if any. if (szServer[0] == '\\' && szServer[1] == '\\') szServer += 2; // Check for '.'. if (!strcmp(szServer, ".")) return TRUE; // Get the server name and compare. char szName[MAX_COMPUTERNAME_LENGTH + 1] = ""; DWORD dwSize = sizeof(szName); GetComputerNameA(szName, &dwSize); return _stricmp(szServer, szName) == 0; }