DWORD Sm_Shiloh::WriteSync(__in SNI_Packet * pPacket, SNI_ProvInfo * pInfo) { BidxScopeAutoSNI3( SNIAPI_TAG _T("%u#, ") _T("pPacket: %p{SNI_Packet*}, ") _T("pInfo: %p{SNI_ProvInfo*}\n"), GetBidId(), pPacket, pInfo ); DWORD dwRet = ERROR_SUCCESS; // Check that the packetsize does not exceed the max packet size if( MAX_BUFFER_SIZE < SNIPacketGetBufferSize(pPacket) ) { dwRet = ERROR_NOT_SUPPORTED; SNI_SET_LAST_ERROR( SM_PROV, SNIE_SYSTEM, dwRet ); goto Exit; } // Post the transport write LONG Error; if( SNIPacketGetBufferSize(pPacket) != g_rgFuncs.Write( m_pConnObj, SNIPacketGetBufPtr(pPacket), (int)SNIPacketGetBufferSize(pPacket), &Error ) ) { dwRet = Error; SNI_SET_LAST_ERROR( SM_PROV, SNIE_1, dwRet ); } Exit: BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwRet); return dwRet; }
DWORD Sm_Shiloh::WriteDone(SNI_Packet ** ppPacket, DWORD dwBytes, DWORD dwError) { BidxScopeAutoSNI4( SNIAPI_TAG _T("%u#, ") _T("ppPacket: %p{SNI_Packet**}, ") _T("dwBytes: %d, ") _T("dwError: %d{WINERR}\n"), GetBidId(), ppPacket, dwBytes, dwError); // If its an error, return the error. Sm_Shiloh does not treat any errors as "valid". if( dwError ) { SNI_SET_LAST_ERROR( SM_PROV, SNIE_1, dwError ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwError); return dwError; } SNI_SET_LAST_ERROR( SM_PROV, SNIE_1, ERROR_FAIL ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_FAIL); return ERROR_FAIL; }
DWORD Sm_Shiloh::LoadDll(__out NLFunctionTable * pFuncs) { BidxScopeAutoSNI1( SNIAPI_TAG _T( "pFuncs: %p{NLFunctionTable*}\n"), pFuncs); DWORD dwError; // Function Names for Wrapper Netlib Dlls - keep in [....] with enum in .hpp CHAR * rgFnName[CLNT_NETFUNCS] = { "ConnectionObjectSize", "ConnectionOpen", "ConnectionRead", "ConnectionWrite", "ConnectionClose", "ConnectionCheckForData" }; FARPROC rgFnPtr[CLNT_NETFUNCS]; if( NULL == (hNetlib = SNILoadSystemLibraryA( "dbmslpcn.dll" )) ) { dwError = GetLastError(); SNI_SET_LAST_ERROR( SM_PROV, SNIE_36, dwError ); goto ErrorExit; } int i; for( i = 0; i < CLNT_NETFUNCS; i++ ) { if( NULL == (rgFnPtr[i] = GetProcAddress(hNetlib, rgFnName[i])) ) { dwError = GetLastError(); SNI_SET_LAST_ERROR( SM_PROV, SNIE_37, dwError ); goto ErrorExit; } } memcpy(pFuncs, rgFnPtr, sizeof(NLFunctionTable)); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_SUCCESS); return ERROR_SUCCESS; ErrorExit: if( hNetlib ) FreeLibrary( hNetlib ); hNetlib = NULL; BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwError); return dwError; }
DWORD DynamicQueue::EnQueue(HANDLE Key) { BidxScopeAutoSNI1( SNIAPI_TAG _T("Key: %p{HANDLE}\n"), Key ); QueueItem *pNew; if(m_pFree) { pNew = m_pFree; m_pFree = m_pFree->pNext; } else { pNew = NewNoX(gpmo) QueueItem; if( pNew == NULL ) { SNI_SET_LAST_ERROR( INVALID_PROV, SNIE_4, ERROR_OUTOFMEMORY ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_OUTOFMEMORY); return ERROR_OUTOFMEMORY; } } pNew->pNext = NULL; pNew->Key = Key; *m_ppTail = pNew; m_ppTail=&pNew->pNext; BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_SUCCESS); return ERROR_SUCCESS; }
DWORD Sm_Shiloh::ReadDone( SNI_Packet ** ppPacket, __out SNI_Packet ** ppLeftOver, DWORD dwBytes, DWORD dwError ) { BidxScopeAutoSNI5( SNIAPI_TAG _T("%u#, ") _T("ppPacket: %p{SNI_Packet**}, ") _T("ppLeftOver: %p{SNI_Packet**}, ") _T("dwBytes: %d, ") _T("dwError: %d{WINERR}\n"), GetBidId(), ppPacket, ppLeftOver, dwBytes, dwError); *ppLeftOver = 0; // If an error has occurred, then let's return that error. // Otherwise, let's force an error. (Sm_Shiloh does not // treat any errors as "valid") // if( !dwError ) dwError = ERROR_FAIL; SNI_SET_LAST_ERROR( SM_PROV, SNIE_1, dwError ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwError); return dwError; }
DWORD Sm_Shiloh::TerminateListener(HANDLE hListener) { BidxScopeAutoSNI1( SNIAPI_TAG _T( "hListener: %p{HANDLE}\n"), hListener ); SNI_SET_LAST_ERROR( SM_PROV, SNIE_15, ERROR_FAIL ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_FAIL); return ERROR_FAIL; }
DWORD Sm_Shiloh::InitializeListener(HANDLE hSNIAcceptKey, void *pListen, HANDLE * pListenHandle) { BidxScopeAutoSNI3( SNIAPI_TAG _T( "hSNIAcceptKey: %p{HANDLE}, pListen: %p, pListenHandle: %p{HANDLE*}\n"), hSNIAcceptKey, pListen, pListenHandle ); SNI_SET_LAST_ERROR( SM_PROV, SNIE_15, ERROR_FAIL ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_FAIL); return ERROR_FAIL; }
DWORD Sm_Shiloh::GatherWriteAsync(SNI_Packet * pPacket, SNI_ProvInfo * pInfo) { BidxScopeAutoSNI3( SNIAPI_TAG _T("%u#, ") _T("pPacket: %p{SNI_Packet*}, ") _T("pInfo: %p{SNI_ProvInfo*}\n"), GetBidId(), pPacket, pInfo ); SNI_SET_LAST_ERROR( SM_PROV, SNIE_15, ERROR_FAIL ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_FAIL); return ERROR_FAIL; }
DWORD Sm_Shiloh::ReadAsync(SNI_Packet ** ppNewPacket, LPVOID pPacketKey) { BidxScopeAutoSNI3( SNIAPI_TAG _T("%u#, ") _T("ppNewPacket: %p{SNI_Packet**}, ") _T("pPacketKey: %p\n"), GetBidId(), ppNewPacket, pPacketKey ); SNI_SET_LAST_ERROR( SM_PROV, SNIE_15, ERROR_FAIL ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_FAIL); return ERROR_FAIL; }
DWORD Sm_Shiloh::Close() { BidxScopeAutoSNI1( SNIAPI_TAG _T("%u#\n"), GetBidId() ); DWORD dwRet = ERROR_SUCCESS; LONG Error; if( FALSE == g_rgFuncs.Close( m_pConnObj, &Error ) ) { dwRet = Error; SNI_SET_LAST_ERROR( SM_PROV, SNIE_1, dwRet ); } delete [] m_pConnObj; m_pConnObj = 0; BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwRet); return dwRet; }
DWORD Sm_Shiloh::AcceptDone( SNI_Conn * pConn, LPVOID pAcceptKey, DWORD dwBytes, DWORD dwError, SNI_Provider ** ppProv, LPVOID * ppAcceptInfo ) { BidxScopeAutoSNI6( SNIAPI_TAG _T("pConn:%p{SNI_Conn*}, ") _T("pAcceptKey:%p, ") _T("dwBytes:%d, ") _T("dwError:%d, ") _T("ppProv:%p{SNI_Provider**}, ") _T("ppAcceptInfo:%p{LPVOID*}\n"), pConn, pAcceptKey, dwBytes, dwError, ppProv, ppAcceptInfo); SNI_SET_LAST_ERROR( SM_PROV, SNIE_15, ERROR_FAIL ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_FAIL); return ERROR_FAIL; }
DWORD Sm_Shiloh::Initialize(PSNI_PROVIDER_INFO pInfo) { BidxScopeAutoSNI1( SNIAPI_TAG _T( "pInfo: %p{PSNI_PROVIDER_INFO}\n"), pInfo ); // Fill all these up pInfo->fBaseProv = TRUE; pInfo->Size = 0; pInfo->Offset = 0; pInfo->ProvNum = SM_PROV; DWORD dwError = SNICritSec::Initialize( &DllCritSec ); if( ERROR_SUCCESS != dwError) { SNI_SET_LAST_ERROR( SM_PROV, SNIE_SYSTEM, dwError ); } BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwError); return dwError; }
DWORD Sm::IsYukonByInstanceString(__in_opt LPSTR szInstance, __out BOOL * pfIsYukon, __out_opt BOOL * pfNew, __out BOOL * pfVersionRetrieved) { BidxScopeAutoSNI4( SNIAPI_TAG _T("szInstance: \"%hs\", pfIsYukon: %p{BOOL*}, pfNew: %p{BOOL*}, pfVersionRetrieved: %p{BOOL*}\n"), szInstance, pfIsYukon, pfNew, pfVersionRetrieved ); DWORD dwError = ERROR_SUCCESS; Assert ( szInstance && szInstance[0] ); Assert ( pfIsYukon != NULL ); Assert ( pfNew != NULL ); if ( szInstance == NULL || szInstance[0] == '\0' || pfIsYukon == NULL || pfNew == NULL || pfVersionRetrieved == NULL ) { dwError = ERROR_INVALID_PARAMETER; goto Exit; } *pfVersionRetrieved = FALSE; *pfNew = FALSE; if ( !gpInstapiStruct ) { *pfIsYukon = FALSE; goto Exit; } WCHAR wszVersion[MAX_VERSION_LENGTH+1]; DWORD cwszVersion = MAX_VERSION_LENGTH; WCHAR wszInstance[MAX_INSTANCENAME_LENGTH+1]; int cRet = MultiByteToWideChar(CP_ACP, 0, szInstance, static_cast<int>(strlen(szInstance))+1, wszInstance, MAX_INSTANCENAME_LENGTH ); if( cRet == 0 ) { dwError = GetLastError(); goto Exit; } wszInstance[MAX_INSTANCENAME_LENGTH] = L'\0'; // For obtain instance ID specifying SQL Server service to make sure we // don't get version for AS or RS. // INST_ID instID; if( !gpInstapiStruct->pfnGetSvcInstanceIDFromName( wszInstance, //instance name SVC_SQL, &instID ) ) { // If we cannot get the version, it is not yukon *pfIsYukon = FALSE; goto Exit; } if( !gpInstapiStruct->pfnGetSQLInstanceRegStringByID( &instID, L"MSSQLSERVER\\CurrentVersion", //RegPath L"CurrentVersion", //ValueName wszVersion, //String &cwszVersion) ) { // If we cannot get the version, it is not yukon *pfIsYukon = FALSE; goto Exit; } wszVersion[MAX_VERSION_LENGTH]=L'\0'; char szVersion[MAX_VERSION_LENGTH+1]; cRet = WideCharToMultiByte( CP_ACP, 0, wszVersion, -1, szVersion, MAX_VERSION_LENGTH, NULL, NULL ); if( cRet == 0 ) { dwError = GetLastError(); goto Exit; } szVersion[MAX_VERSION_LENGTH]='\0'; //4. We got Yukon Version number now! *pfIsYukon = FALSE; LPSTR szTmp = strchr(szVersion, '.'); if( szTmp ) { //szTmp = strtok(szVersion, "."); *szTmp = 0; int iMajorVer = _atoi_l(szVersion, GetDefaultLocale()); if( 9 == iMajorVer ) { *pfIsYukon = TRUE; szTmp = szTmp + 1; szTmp = strchr(szTmp, '.'); if( szTmp ) { szTmp = szTmp + 1; if( 579 <= _atoi_l(szTmp, GetDefaultLocale()) ) *pfNew = TRUE; } } else if( 9 < iMajorVer ) { *pfIsYukon = TRUE; *pfNew = TRUE; } *pfVersionRetrieved = TRUE; } Exit: BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwError); if ( ERROR_SUCCESS != dwError ) SNI_SET_LAST_ERROR( SM_PROV, SNIE_36 , dwError ); return dwError; }
DWORD Sm::LoadInstapiIfNeeded() { DWORD dwError = ERROR_SUCCESS; INSTAPILIBSTRUCT* pInstapiStruct = NULL; BidxScopeAutoSNI0( SNIAPI_TAG _T("\n") ); // Check to see if instapdll is already loaded // if (InterlockedCompareExchangePointer ( reinterpret_cast<volatile PVOID*>(&gpInstapiStruct), NULL, NULL)) { goto ErrorExit; } pInstapiStruct = NewNoX(gpmo) INSTAPILIBSTRUCT; if ( NULL == pInstapiStruct ) { dwError = ERROR_OUTOFMEMORY; goto ErrorExit; } pInstapiStruct -> hInstapidll = NULL; // Temparorily load the DLL. //1. Read registry value SharedCode under HKLM\Software\Microsoft\Microsoft SQL Server\90\Shared, const char szSharedPathLocation[]="Software\\Microsoft\\Microsoft SQL Server\\90"; HKEY hKey; dwError = static_cast<DWORD> (RegOpenKeyEx( HKEY_LOCAL_MACHINE,// handle to open key szSharedPathLocation, // subkey name 0, // reserved KEY_QUERY_VALUE, // security access mask &hKey )); // handle to open key if( ERROR_SUCCESS != dwError ) { BidTrace1(ERROR_TAG _T("Cannot retrieve the shared path. %d{WINERR}\n"), dwError); goto ErrorExit; } char szSharedPath[MAX_PATH+1]; DWORD cszSharedPath = MAX_PATH; DWORD dwSharedPathRegType; dwError = static_cast<DWORD> ( RegQueryValueEx( hKey, // handle to key "SharedCode", // value name 0, // reserved &dwSharedPathRegType, // value type (LPBYTE)szSharedPath, // value data &cszSharedPath )); // size of value data RegCloseKey( hKey ); if( ERROR_SUCCESS != dwError ) { BidTrace1(ERROR_TAG _T("Cannot retrieve the shared path. %d{WINERR}\n"), dwError); goto ErrorExit; } if(REG_SZ != dwSharedPathRegType) { // RegValue is corrupted. In this case, we error out. dwError = ERROR_INVALID_DATA; goto ErrorExit; } __analysis_assume(cszSharedPath<=MAX_PATH); //The current header we use does not annotate RegQueryValueEx correctly, adding this to suppress Prefast 26015, we could remove it when the tools set is updated to Vista SDK. // Ensure NULL-termination. szSharedPath[cszSharedPath] = '\0'; //2. Load instapi.dll from the location where SharedCode points to const char szInstapidllname[] ="instapi.dll"; char szInstapipath[MAX_PATH+sizeof(szInstapidllname)+1]; if(FAILED(StringCchPrintf_lA( szInstapipath, CCH_ANSI_STRING(szInstapipath), "%s%s", GetDefaultLocale(),szSharedPath,szInstapidllname))) { dwError = ERROR_INVALID_PARAMETER; goto ErrorExit; } szInstapipath[sizeof(szInstapipath)-1] = '\0'; if( NULL == (pInstapiStruct->hInstapidll = LoadLibrary( szInstapipath)) ) { dwError = GetLastError(); BidTrace1(ERROR_TAG _T("Failed to load instapi.dll. %d{WINERR}\n"), dwError ); goto ErrorExit; } const char * szGetSvcInstanceIDFromName = "GetSvcInstanceIDFromName"; if( !(pInstapiStruct->pfnGetSvcInstanceIDFromName = (PFNGetSvcInstanceIDFromName)GetProcAddress( pInstapiStruct->hInstapidll, szGetSvcInstanceIDFromName)) ) { dwError = GetLastError(); BidTrace1(ERROR_TAG _T("Failed to load function GetSvcInstanceIDFromName. %d{WINERR}\n"), dwError ); goto ErrorExit; } const char * szGetSQLInstanceRegStringByID = "GetSQLInstanceRegStringByID"; if( !(pInstapiStruct->pfnGetSQLInstanceRegStringByID = (PFNGetSQLInstanceRegStringByID)GetProcAddress( pInstapiStruct->hInstapidll, szGetSQLInstanceRegStringByID)) ) { dwError = GetLastError(); BidTrace1(ERROR_TAG _T("Failed to load function GetSQLInstanceRegStringByID. %d{WINERR}\n"), dwError ); goto ErrorExit; } Assert (ERROR_SUCCESS == dwError ); // Now try to set global gpInstapiStruct if ( InterlockedCompareExchangePointer ( reinterpret_cast<volatile PVOID*>(&gpInstapiStruct), reinterpret_cast<PVOID>(pInstapiStruct) ,NULL)) { goto ErrorExit; } BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("Loaded instapi.dll. %d{WINERR}\n"), dwError ); return dwError; ErrorExit: if ( pInstapiStruct ) { if ( pInstapiStruct -> hInstapidll ) FreeLibrary( pInstapiStruct -> hInstapidll ); delete pInstapiStruct; } if ( ERROR_SUCCESS != dwError ) SNI_SET_LAST_ERROR( SM_PROV, SNIE_36, dwError ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwError ); return dwError; }
DWORD Sm::GetThreadSID( __out SID ** ppSID ) { BidxScopeAutoSNI1( SNIAPI_TAG _T( "ppSID: %p{SID**}\n"), ppSID ); BOOL fReturn = FALSE; HANDLE TokenHandle = NULL; PTOKEN_USER pUserToken = NULL; DWORD dwSizeNeeded = 0; DWORD dwError = ERROR_SUCCESS; *ppSID = NULL; fReturn = OpenThreadToken( GetCurrentThread(), TOKEN_READ, FALSE, &TokenHandle ); if( FALSE == fReturn ) { // If this was because there was no token for the thread, then // use the token of the process if( ERROR_NO_TOKEN == (dwError = GetLastError()) ) { fReturn = OpenProcessToken( GetCurrentProcess(), TOKEN_READ, &TokenHandle ); if( FALSE == fReturn ) { dwError = GetLastError(); SNI_SET_LAST_ERROR( SM_PROV, SNIE_10, dwError ); } } else { dwError = GetLastError(); SNI_SET_LAST_ERROR( SM_PROV, SNIE_10, dwError ); } if( FALSE == fReturn ) goto ErrorExit; } fReturn = GetTokenInformation( TokenHandle, TokenUser, NULL, 0, &dwSizeNeeded ); if( FALSE == fReturn ) { if( ERROR_INSUFFICIENT_BUFFER != (dwError = GetLastError()) ) { SNI_SET_LAST_ERROR( SM_PROV, SNIE_10, dwError ); goto ErrorExit; } } pUserToken = (PTOKEN_USER) NewNoX(gpmo) BYTE[dwSizeNeeded]; if( !pUserToken ) { dwError = ERROR_OUTOFMEMORY; SNI_SET_LAST_ERROR( SM_PROV, SNIE_4, dwError ); goto ErrorExit; } fReturn = GetTokenInformation( TokenHandle, TokenUser, (LPVOID) pUserToken, dwSizeNeeded, &dwSizeNeeded ); if( FALSE == fReturn ) { dwError = GetLastError(); SNI_SET_LAST_ERROR( SM_PROV, SNIE_10, dwError ); goto ErrorExit; } // Validate the SID before copying. // if( !IsValidSid( pUserToken->User.Sid ) ) { dwError = GetLastError(); SNI_SET_LAST_ERROR( SM_PROV, SNIE_10, dwError ); goto ErrorExit; } // Let's make a copy the SID // dwSizeNeeded = GetLengthSid( pUserToken->User.Sid ); *ppSID = (SID *) NewNoX(gpmo) BYTE[dwSizeNeeded]; if( !*ppSID ) { dwError = ERROR_OUTOFMEMORY; SNI_SET_LAST_ERROR( SM_PROV, SNIE_4, dwError ); goto ErrorExit; } fReturn = CopySid( dwSizeNeeded, *ppSID, pUserToken->User.Sid ); if( FALSE == fReturn ) { dwError = GetLastError(); SNI_SET_LAST_ERROR( SM_PROV, SNIE_10, dwError ); goto ErrorExit; } delete [] pUserToken; CloseHandle( TokenHandle ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_SUCCESS); return ERROR_SUCCESS; ErrorExit: if( pUserToken ) delete [] pUserToken; if( *ppSID ) delete [] *ppSID; *ppSID = 0; if( TokenHandle ) CloseHandle( TokenHandle ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwError); return dwError; }
DWORD Sm::OpenWithFallback( __in SNI_CONSUMER_INFO * pConsumerInfo, __out SNI_Conn ** ppConn, __in ProtElem * pProtElem, __out SNI_Provider ** ppProv, BOOL fSync ) { BidxScopeAutoSNI5( SNIAPI_TAG _T( "pConsumerInfo: %p{SNI_CONSUMER_INFO*}, ppConn: %p{SNI_Conn**}, pProtElem: %p{ProtElem*}, ppProv: %p{SNI_Provider**}, fSync: %d{BOOL}\n"), pConsumerInfo, ppConn, pProtElem, ppProv, fSync); DWORD dwError = ERROR_SUCCESS; BOOL fQAdded = FALSE; BOOL fNewer = FALSE; // Tmpry Sm *pSm = NULL; // For Shiloh connectivity BOOL fSNIenabled = FALSE; BOOL fSrvVersionRetrieved = FALSE; // Set the instance LPSTR szInstance = NULL; *ppConn = NULL; szInstance = StrChrA_SYS(pProtElem->Sm.Alias,(int) strlen(pProtElem->Sm.Alias), '\\'); if( szInstance ) (szInstance) += 1; else szInstance = "MSSQLSERVER"; #ifdef SNI_BASED_CLIENT //Load instapi and set global flag gdwfInstapidll (void) LoadInstapiIfNeeded(); // Do not connect over shared memory to a clustered server if( Sm::IsClustered(szInstance) ) { SNI_SET_LAST_ERROR( SM_PROV, SNIE_29, ERROR_NOT_SUPPORTED ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("Cluster is not supported over shared memory. %d{WINERR}\n"), ERROR_NOT_SUPPORTED); dwError = ERROR_NOT_SUPPORTED; goto ErrorExit; } // Check if this server instance is SNI-based or not if( ERROR_SUCCESS != (dwError = Sm::IsYukonByInstanceString(szInstance, &fSNIenabled, &fNewer, &fSrvVersionRetrieved)) ) goto ErrorExit; // If the server is Yukon+ or we failed to retrieve the server's // version try Yukon's LPC first (the latter can happen, e.g. // when talking to a Yukon IDW14/15 server across 32/64-bit // boundary). Assert( fSrvVersionRetrieved || !fSNIenabled ); // Yukon server is not supported on Win9x. if( fSNIenabled && gfIsWin9x ) { SNI_SET_LAST_ERROR( SM_PROV, SNIE_14, ERROR_NOT_SUPPORTED ); dwError = ERROR_NOT_SUPPORTED; goto ErrorExit; } #else // #ifdef SNI_BASED_CLIENT fSNIenabled = TRUE; fNewer = TRUE; fSrvVersionRetrieved = TRUE; #endif // #else ... #ifdef SNI_BASED_CLIENT if( ( fSNIenabled || !fSrvVersionRetrieved ) && !gfIsWin9x ) { // Try Yukon's NP-based LPC. // Assert( NULL == *ppConn ); dwError = Sm::OpenNpBasedYukon( pConsumerInfo, ppConn, pProtElem, ppProv, fSync ); if( ERROR_SUCCESS == dwError ) { goto SuccessExit; } if( fSNIenabled || !fSync ) { goto ErrorExit; } // Otherwise, we failed to retrieve the server version, failed // to make a Yukon LPC connection, and the connection is [....], // so fall back and try Shiloh LPC connection. } #ifdef SNI_BASED_CLIENT // If we got here either we retrieved pre-Yukon version or we failed // to retrieve server version and failed to connect over Yukon LPC. // Try Shiloh LPC now. Assert( !fSNIenabled ); // If this is an Aysnc connection - return error. // Async is NOT supported for Shiloh servers. if( !fSync ) { SNI_SET_LAST_ERROR( SM_PROV, SNIE_3, ERROR_NOT_SUPPORTED ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("SQL Server 2000 does not support Async Shared Memory Connection. %d{WINERR}\n"), ERROR_NOT_SUPPORTED); dwError = ERROR_NOT_SUPPORTED; goto ErrorExit; } SNI_Conn * pConn = NULL; dwError = Sm::CreateSNIConn( pConsumerInfo, &pConn, pProtElem, fSync ); if( ERROR_SUCCESS != dwError ) { Assert( NULL == pConn ); goto ErrorExit; } dwError = Sm_Shiloh::Open(pConn, pProtElem, ppProv); if( ERROR_SUCCESS != dwError ) { pConn->Release( REF_Active ); pConn = NULL; goto ErrorExit; } *ppConn = pConn; pConn = NULL; #endif // #ifdef SNI_BASED_CLIENT SuccessExit: BidTraceU3( SNI_BID_TRACE_ON, RETURN_TAG _T("*ppConn: %p{SNI_Conn*}, *ppProv: %p{SNI_Provider*}, %d{WINERR}\n"), *ppConn, *ppProv, dwError); return dwError; ErrorExit: BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwError); return dwError; }
// This is a wrapper around NewNoX call to eliminate exception handler // set up/teardown in the calling function; we do not want to inline // this. friend SNI_Packet * SNIPacketNew( __in SNI_Conn * pConn, SNI_Packet_IOType IOType, SNIMemRegion * pMemRegion, DWORD MemTag, DWORD dwSize, SOS_IOCompRoutine* IOCompRoutine, ConsumerNum ConsNum ) { BidTraceU2( SNI_BID_TRACE_ON, SNIAPI_TAG _T( "pConn: %p{SNI_Conn*}, IOType: %d\n"), pConn, IOType); DWORD dwError = ERROR_SUCCESS; Assert(IOType < SNI_Packet_InvalidType); Assert(ConsNum < SNI_Consumer_Invalid); #ifndef SNI_BASED_CLIENT Assert ( pMemRegion && pMemRegion->GetPacketPmo() ); SNI_Packet * pPacket = NewNoX(pMemRegion->GetPacketPmo()) SNI_Packet( dwSize, pConn, IOCompRoutine, MemTag, pMemRegion, IOType, ConsNum); #else SNI_Packet * pPacket = NewNoX(gpmo) SNI_Packet( dwSize, pConn, IOCompRoutine, MemTag, pMemRegion, IOType, ConsNum); #endif if (NULL == pPacket) // SNI_Packet object allocation failed { dwError = ERROR_OUTOFMEMORY; goto ret; } else if( ((SNI_Packet_Read == IOType) || // If IOType is Read or Write (SNI_Packet_Write == IOType)) && // we must have a buffer allocated successfully (NULL == pPacket->m_pBuffer) ) { delete pPacket; pPacket = NULL; dwError = ERROR_OUTOFMEMORY; goto ret; } #ifdef SNI_BASED_CLIENT dwError = pPacket->InitOvlEvent(); if (ERROR_SUCCESS != dwError) { // Already BID-traced at InitOvlEvent delete pPacket; pPacket = NULL; goto ret; } #endif ret: if( NULL == pPacket ) { SNI_SET_LAST_ERROR( INVALID_PROV, SNIE_SYSTEM, dwError ); } BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%p{SNI_Packet*}\n"), pPacket); return (SNI_Packet *)pPacket; }
// Note: This call is for allocating packets with explicit specifying of Consumer // The main reason is to force Consumer specification when "varying" packets are allocated. friend SNI_Packet * SNIPacketAllocateEx2(SNI_Conn * pConn, SNI_Packet_IOType IOType, ConsumerNum ConsNum) { BidTraceU3( SNI_BID_TRACE_ON, SNIAPI_TAG _T( "pConn: %p{SNI_Conn*}, IOType: %d, consumer: %d\n"), pConn, IOType, ConsNum); Assert( IOType < SNI_Packet_InvalidType ); Assert( ConsNum < SNI_Consumer_Invalid ); SNI_Packet * pPacket = NULL; SNIMemRegion * pMemRegion = 0; DWORD MemTag; DWORD cBufferSize; SOS_IOCompRoutine* IOCompRoutine; // This should be really maintained by SNI_Conn but for safety // reasons we will check it here. if( pConn->m_ConnInfo.ConsBufferSize + pConn->m_ConnInfo.ProvBufferSize > SNIMemRegion::GetBlockSize(pConn->m_MemTag) ) { SNI_SET_LAST_ERROR( INVALID_PROV, SNIE_SYSTEM, ERROR_INVALID_PARAMETER ); BidTrace3( ERROR_TAG _T( "ConsBufferSize: %d, ProvBufferSize: %d, m_MemTag: %d{MemTagTypes}\n" ), pConn->m_ConnInfo.ConsBufferSize, pConn->m_ConnInfo.ProvBufferSize, pConn->m_MemTag ); goto ret; } GET_SNI_MEM_REGION(pConn, pMemRegion); // The if statement above made sure the following assert is true Assert( pConn->m_MemTag < MAX_MEM_TAGS ); // DEVNOTE: MemTag is not used at the preceeding validation statements // to avoid elimination of the verification, which is part of security checks // The verification above should be valid no matter what type of packet we are // allocating. switch (IOType) { case SNI_Packet_KeyHolderNoBuf: case SNI_Packet_VaryingBufferRead: MemTag = REG_0K; cBufferSize = BUF_0K; IOCompRoutine = (SOS_IOCompRoutine *)SNIReadDone; break; case SNI_Packet_VaryingBufferWrite: MemTag = REG_0K; cBufferSize = BUF_0K; IOCompRoutine = (SOS_IOCompRoutine *)SNIWriteDone; break; case SNI_Packet_Read: MemTag = pConn->m_MemTag; cBufferSize = pConn->m_ConnInfo.ConsBufferSize + pConn->m_ConnInfo.ProvBufferSize; IOCompRoutine = (SOS_IOCompRoutine *)SNIReadDone; break; case SNI_Packet_Write: MemTag = pConn->m_MemTag; cBufferSize = pConn->m_ConnInfo.ConsBufferSize + pConn->m_ConnInfo.ProvBufferSize; IOCompRoutine = (SOS_IOCompRoutine *)SNIWriteDone; break; default: Assert(false && "Invalid Packet IOType specified\n"); // Invalid IOType goto ret; } // First, try to get this from the cache if( NULL == (pPacket = pMemRegion[MemTag].Pop())) { // If we do not find it in the cache, then allocate a new object pPacket = SNIPacketNew(pConn, IOType, &pMemRegion[MemTag], MemTag, cBufferSize, IOCompRoutine, ConsNum); if (NULL == pPacket) goto ret; } else { #ifndef SNI_BASED_CLIENT Assert ( pPacket -> m_bMemTag == MemTag && pPacket ->m_pMemRegion == &pMemRegion[MemTag]); #endif // Set the packet buffer size pPacket->m_cBufferSize = cBufferSize; pPacket->m_pConn = pConn; pPacket->m_OffSet = 0; pPacket->m_cbBuffer = 0; // Packets from REG_0K might be SNI_Packet_KeyHolderNoBuf or SNI_Packet_VaryingBuffer* pPacket->m_IOType = IOType; pPacket->m_ConsBuf = ConsNum; #ifndef SNI_BASED_CLIENT // This flag should have been reset before it got put in the pool. // Nevertheless as a defensive programming measure, we will unset // it here just like the other flags. Assert(!pPacket->m_fZeroPayloadOnRelease); pPacket->m_fZeroPayloadOnRelease = FALSE; pPacket->m_cbBytesToZero = 0; #endif // ifndef SNI_BASED_CLIENT pPacket->Init(0, 0, IOCompRoutine, pPacket, FALSE); pPacket->SetErrorCode(ERROR_SUCCESS); // If the packet came from the cache, reset it's ref count to 1. Assert(0==pPacket->m_cRef); pPacket->m_cRef = 1; BidTraceU2( SNI_BID_TRACE_ON, SNI_TAG _T("%u#{SNI_Packet} from pool for %u#{SNI_Conn}\n"), SNIPacketGetBidId(pPacket), pConn->GetBidId() ); } Assert(1==pPacket->m_cRef); // Set the offset correctly - for Write buffers ONLY if( IOType == SNI_Packet_Write ) { pPacket->m_OffSet = pConn->m_ConnInfo.ProvOffset; } #ifdef SNI_BASED_CLIENT // Set Event handle to Overlapped structure for [....] connections if (pConn->m_fSync) { pPacket->AddOvlEvent(); } #endif if ((SNI_Packet_Read == IOType) || (SNI_Packet_Write == IOType)) { pConn->AddRef(REF_Packet); } else { pConn->AddRef(REF_PacketNotOwningBuf); } ret: BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%p{SNI_Packet*}\n"), pPacket); return (SNI_Packet *)pPacket; }
DWORD Sm_Shiloh::ReadSync(__out SNI_Packet ** ppNewPacket, int timeout) { BidxScopeAutoSNI3( SNIAPI_TAG _T("%u#, ") _T("ppNewPacket: %p{SNI_Packet**}, ") _T("timeout: %d\n"), GetBidId(), ppNewPacket, timeout ); DWORD dwRet = ERROR_SUCCESS; *ppNewPacket = 0; // Check for 0 timeout - proceed only if there is data if( 0 == timeout) { LONG Error, cBytes; if( FALSE == g_rgFuncs.CheckData( m_pConnObj, &cBytes, &Error) ) { if( Error ) { SNI_SET_LAST_ERROR( SM_PROV, SNIE_1, static_cast<DWORD>(Error) ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), Error); return Error; } else { SNI_SET_LAST_ERROR( SM_PROV, SNIE_SYSTEM, WAIT_TIMEOUT ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), WAIT_TIMEOUT); return WAIT_TIMEOUT; } } // Since we already have data, call Read iwth infinite timeout timeout = -1; } // Allocate a new packet SNI_Packet * pPacket = SNIPacketAllocate(m_pConn, SNI_Packet_Read); if( !pPacket ) { dwRet = ERROR_OUTOFMEMORY; SNI_SET_LAST_ERROR( SM_PROV, SNIE_SYSTEM, dwRet ); goto ErrorExit; } // Post the transport read DWORD dwBytesRead = 0; { LONG Error; #define NETE_TIMEOUT -2 #define NET_IMMEDIATE 0xFFFF // Convert from Shiloh timeout format to Yukon // For Yukon, // -1 = INFINITE // 0 = ZERO // Others - MilliSecs // For Shiloh, // NET_IMMEDIATE = ZERO // 0 = INFINITE // Others - Secs if( -1 == timeout ) timeout = 0; else if( 0 == timeout ) timeout = NET_IMMEDIATE; else timeout /= 1000; dwBytesRead = g_rgFuncs.Read( m_pConnObj, SNIPacketGetBufPtr(pPacket), (int)SNIPacketGetBufActualSize(pPacket), (int)SNIPacketGetBufActualSize(pPacket), (USHORT)timeout, &Error ); if( Error == NETE_TIMEOUT ) { dwRet = WAIT_TIMEOUT; SNI_SET_LAST_ERROR( SM_PROV, SNIE_SYSTEM, dwRet ); goto ErrorExit; } if( 0 == dwBytesRead ) { dwRet = Error; SNI_SET_LAST_ERROR( SM_PROV, SNIE_1, dwRet ); goto ErrorExit; } } SNIPacketSetBufferSize( pPacket, dwBytesRead ); *ppNewPacket = pPacket; BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwRet); return dwRet; ErrorExit: if( pPacket ) SNIPacketRelease( pPacket ); *ppNewPacket = NULL; BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwRet); return dwRet; }
DWORD Sm::GetThreadSID( SID ** ppSID ) { BidxScopeAutoSNI1( SNIAPI_TAG _T( "ppSID: %p{SID**}\n"), ppSID ); BOOL fReturn = FALSE; HANDLE TokenHandle = NULL; PTOKEN_USER pUserToken = NULL; DWORD dwSizeNeeded = 0; DWORD dwError = ERROR_SUCCESS; PSID pSID = NULL; *ppSID = NULL; BOOL fThreadSID = OpenThreadToken( GetCurrentThread(), TOKEN_READ, FALSE, &TokenHandle ); if (fThreadSID) { fReturn = GetTokenInformation( TokenHandle, TokenUser, NULL, 0, &dwSizeNeeded ); if( FALSE == fReturn ) { if( ERROR_INSUFFICIENT_BUFFER != (dwError = GetLastError()) ) { SNI_SET_LAST_ERROR( SM_PROV, SNIE_10, dwError ); goto ErrorExit; } } pUserToken = (PTOKEN_USER) NewNoX(gpmo) BYTE[dwSizeNeeded]; if( !pUserToken ) { dwError = ERROR_OUTOFMEMORY; SNI_SET_LAST_ERROR( SM_PROV, SNIE_4, dwError ); goto ErrorExit; } fReturn = GetTokenInformation( TokenHandle, TokenUser, (LPVOID) pUserToken, dwSizeNeeded, &dwSizeNeeded ); if( FALSE == fReturn ) { dwError = GetLastError(); SNI_SET_LAST_ERROR( SM_PROV, SNIE_10, dwError ); goto ErrorExit; } pSID = pUserToken->User.Sid; } //Grab the Process SID (which is already available from the SOS) else { //We merely grab the SID for the process if( ERROR_NO_TOKEN == (dwError = GetLastError())) { pSID = SOS_OS::GetProcessSID(); } else { dwError = GetLastError(); SNI_SET_LAST_ERROR( SM_PROV, SNIE_10, dwError ); goto ErrorExit; } } // Validate the SID before copying. // if( !IsValidSid( pSID ) ) { dwError = GetLastError(); SNI_SET_LAST_ERROR( SM_PROV, SNIE_10, dwError ); goto ErrorExit; } // Let's make a copy the SID // dwSizeNeeded = GetLengthSid( pSID ); *ppSID = (SID *) NewNoX(gpmo) BYTE[dwSizeNeeded]; if( !*ppSID ) { dwError = ERROR_OUTOFMEMORY; SNI_SET_LAST_ERROR( SM_PROV, SNIE_4, dwError ); goto ErrorExit; } fReturn = CopySid( dwSizeNeeded, *ppSID, pSID ); if( FALSE == fReturn ) { dwError = GetLastError(); SNI_SET_LAST_ERROR( SM_PROV, SNIE_10, dwError ); goto ErrorExit; } //We never obtained a user token at all if this is a process sid if (fThreadSID) { delete [] pUserToken; CloseHandle( TokenHandle ); } BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_SUCCESS); return ERROR_SUCCESS; ErrorExit: if( fThreadSID && pUserToken ) delete [] pUserToken; if( *ppSID ) delete [] *ppSID; *ppSID = 0; if( fThreadSID && TokenHandle ) CloseHandle( TokenHandle ); BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwError); return dwError; }
DWORD Sm_Shiloh::Open( SNI_Conn * pConn, ProtElem * pProtElem, __out SNI_Provider ** ppProv ) { BidxScopeAutoSNI3( SNIAPI_TAG _T("pConn: %p{SNI_Conn*}, ") _T("pProtElem: %p{ProtElem*}, ") _T("ppProv: %p{SNI_Provider**}\n"), pConn, pProtElem, ppProv); Sm_Shiloh * pSm_ShilohProv = 0; DWORD dwRet = ERROR_FAIL; // If we failed to initialize the SM SHiloh shim, faill // all connections to Shiloh. // if( NULL == DllCritSec ) { dwRet = ERROR_INVALID_STATE; SNI_SET_LAST_ERROR( SM_PROV, SNIE_SYSTEM, dwRet ); goto ErrorExit; } { CAutoSNICritSec a_csDll( DllCritSec, SNI_AUTOCS_DO_NOT_ENTER ); pSm_ShilohProv = NewNoX(gpmo) Sm_Shiloh(pConn); if( !pSm_ShilohProv ) { dwRet = ERROR_OUTOFMEMORY; SNI_SET_LAST_ERROR( SM_PROV, SNIE_SYSTEM, dwRet ); goto ErrorExit; } // Set the handle to be invalid pSm_ShilohProv->m_hNwk = INVALID_HANDLE_VALUE; // Load the Dll, if necessary // a_csDll.Enter(); if( NULL == hNetlib ) { if( ERROR_SUCCESS != (dwRet = Sm_Shiloh::LoadDll(&g_rgFuncs)) ) { a_csDll.Leave(); goto ErrorExit; } } a_csDll.Leave(); } // Check if Shared Memory is valid { // Get the instance LPWSTR wszInstance = NULL; wszInstance = StrChrW_SYS(pProtElem->Sm.Alias,(int) wcslen(pProtElem->Sm.Alias), L'\\' ); if( wszInstance ) wszInstance += 1; else wszInstance = L"MSSQLSERVER"; CONNECTIONVALIDSHAREDMEMORY_FN ConnectionValidSharedMemory; // Let's make sure Shared-Memory Netlib is valid (correct version, matchup, etc.) ConnectionValidSharedMemory = (CONNECTIONVALIDSHAREDMEMORY_FN)GetProcAddress( hNetlib, "ConnectionValidSharedMemory" ); if( !ConnectionValidSharedMemory || !ConnectionValidSharedMemory(wszInstance) ) { dwRet = ERROR_INVALID_PARAMETER; SNI_SET_LAST_ERROR( SM_PROV, SNIE_39, dwRet ); goto ErrorExit; } } pSm_ShilohProv->m_pConnObj = NewNoX (gpmo) BYTE[g_rgFuncs.Size()]; if( !pSm_ShilohProv->m_pConnObj ) { dwRet = ERROR_OUTOFMEMORY; SNI_SET_LAST_ERROR( SM_PROV, SNIE_SYSTEM, dwRet ); goto ErrorExit; } LONG Error = ERROR_SUCCESS; if( !g_rgFuncs.Open(pSm_ShilohProv->m_pConnObj, pProtElem->Sm.Alias, &Error) ) { // If the netlibs function returned an error, use it. // Otherwise, return a generic one. if( ERROR_SUCCESS != Error ) { dwRet = static_cast<DWORD>(Error); } else { dwRet = ERROR_NOT_CONNECTED; } SNI_SET_LAST_ERROR( SM_PROV, SNIE_38, dwRet ); goto ErrorExit; } BidUpdateItemIDA( pSm_ShilohProv->GetBidIdPtr(), SNI_ID_TAG "connection: %p{ProtElem}", pProtElem ); // Set the out provider param to point to the new Sm_Shiloh object *ppProv = pSm_ShilohProv; BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), ERROR_SUCCESS); return ERROR_SUCCESS; ErrorExit: if( pSm_ShilohProv ) { if( pSm_ShilohProv->m_pConnObj ) delete [] pSm_ShilohProv->m_pConnObj; delete pSm_ShilohProv; } *ppProv = NULL; BidTraceU1( SNI_BID_TRACE_ON, RETURN_TAG _T("%d{WINERR}\n"), dwRet); return dwRet; }