Beispiel #1
0
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;
}                    
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}                    
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
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;
	
}
Beispiel #14
0
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;
}	
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
	// 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;
	}
Beispiel #18
0
	// 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;
	}
Beispiel #19
0
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;

}
Beispiel #20
0
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;
}
Beispiel #21
0
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;
}