Repository: microsoft/go-mssqldb
Pull request #71 (2022-11-29 14:00:59)

Get latest commits from upstream
We haven't been trying to push commits back upstream but the source fork has taken a few fixes that we should also try to get.



Patch:
diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml
deleted file mode 100644
index 8c3a92c..0000000
--- a/.github/workflows/pr-validation.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-name: pr-validation
-
-on:
-  pull_request:
-    branches:
-    - main
-
-jobs:
-  build:
-    runs-on: ubuntu-latest
-    strategy:
-      matrix:
-        go: ['1.16','1.17', '1.18']
-        sqlImage: ['2017-latest','2019-latest']
-    steps:
-    - uses: actions/checkout@v2
-    - name: Setup go
-      uses: actions/setup-go@v2
-      with:
-        go-version: '${{ matrix.go }}'
-    - name: Run tests against Linux SQL
-      run: |
-        go version
-        go get -d
-        export SQLCMDPASSWORD=$(date +%s|sha256sum|base64|head -c 32)
-        export SQLCMDUSER=sa
-        export SQLUSER=sa
-        export SQLPASSWORD=$SQLCMDPASSWORD
-        export DATABASE=test
-        docker run -m 2GB -e ACCEPT_EULA=1 -d --name sqlserver -p:1433:1433 -e SA_PASSWORD=$SQLCMDPASSWORD mcr.microsoft.com/mssql/server:${{ matrix.sqlImage }}
-        sleep 10
-        sqlcmd -Q "CREATE DATABASE test"
-        go test -race -cpu 4 ./...
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index c282e9a..0000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Contributing
-
-This project welcomes contributions and suggestions. Most contributions require you to
-agree to a Contributor License Agreement (CLA) declaring that you have the right to,
-and actually do, grant us the rights to use your contribution. For details, visit
-https://cla.microsoft.com.
-
-When you submit a pull request, a CLA-bot will automatically determine whether you need
-to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the
-instructions provided by the bot. You will only need to do this once across all repositories using our CLA.
-
-This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
-For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
-or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
\ No newline at end of file
diff --git a/LICENSE.txt b/LICENSE.txt
index 700e114..7448756 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,5 +1,4 @@
 Copyright (c) 2012 The Go Authors. All rights reserved.
-Copyright (c) Microsoft Corporation.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
diff --git a/README.md b/README.md
index b197e9e..88c79e2 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,16 @@
 # A pure Go MSSQL driver for Go's database/sql package
 
-[![Go Reference](https://pkg.go.dev/badge/github.com/microsoft/go-mssqldb.svg)](https://pkg.go.dev/github.com/microsoft/go-mssqldb)
-[![Build status](https://ci.appveyor.com/api/projects/status/jrln8cs62wj9i0a2?svg=true)](https://ci.appveyor.com/project/microsoft/go-mssqldb)
-[![codecov](https://codecov.io/gh/microsoft/go-mssqldb/branch/master/graph/badge.svg)](https://codecov.io/gh/microsoft/go-mssqldb)
+[![Go Reference](https://pkg.go.dev/badge/github.com/denisenkom/go-mssqldb.svg)](https://pkg.go.dev/github.com/denisenkom/go-mssqldb)
+[![Build status](https://ci.appveyor.com/api/projects/status/jrln8cs62wj9i0a2?svg=true)](https://ci.appveyor.com/project/denisenkom/go-mssqldb)
+[![codecov](https://codecov.io/gh/denisenkom/go-mssqldb/branch/master/graph/badge.svg)](https://codecov.io/gh/denisenkom/go-mssqldb)
+
+For more recent updates, see the [Microsoft fork](https://github.com/microsoft/go-mssqldb).
 
 ## Install
 
 Requires Go 1.8 or above.
 
-Install with `go install github.com/microsoft/go-mssqldb@latest`.
+Install with `go get github.com/denisenkom/go-mssqldb` .
 
 ## Connection Parameters and DSN
 
@@ -22,18 +24,17 @@ Other supported formats are listed below.
 * `password`
 * `database`
 * `connection timeout` - in seconds (default is 0 for no timeout), set to 0 for no timeout. Recommended to set to 0 and use context to manage query and connection timeouts.
-* `dial timeout` - in seconds (default is 15 times the number of registered protocols), set to 0 for no timeout.
+* `dial timeout` - in seconds (default is 15), set to 0 for no timeout
 * `encrypt`
   * `disable` - Data send between client and server is not encrypted.
   * `false` - Data sent between client and server is not encrypted beyond the login packet. (Default)
   * `true` - Data sent between client and server is encrypted.
 * `app name` - The application name (default is go-mssqldb)
-* `authenticator` - Can be used to specify use of a registered authentication provider. (e.g. ntlm, winsspi (on windows) or krb5 (on linux))
 
 ### Connection parameters for ODBC and ADO style connection strings
 
 * `server` - host or host\instance (default localhost)
-* `port` - specifies the host\instance port (default 1433). If instance name is provided but no port, the driver will use SQL Server Browser to discover the port.
+* `port` - used only when there is no instance in server (default 1433)
 
 ### Less common parameters
 
@@ -55,37 +56,10 @@ Other supported formats are listed below.
   * true - Server certificate is not checked. Default is true if encrypt is not specified. If trust server certificate is true, driver accepts any certificate presented by the server and any host name in that certificate. In this mode, TLS is susceptible to man-in-the-middle attacks. This should be used only for testing.
 * `certificate` - The file that contains the public key certificate of the CA that signed the SQL Server certificate. The specified certificate overrides the go platform specific CA certificates.
 * `hostNameInCertificate` - Specifies the Common Name (CN) in the server certificate. Default value is the server host.
-* `tlsmin` - Specifies the minimum TLS version for negotiating encryption with the server. Recognized values are `1.0`, `1.1`, `1.2`, `1.3`. If not set to a recognized value the default value for the `tls` package will be used. The default is currently `1.2`. 
 * `ServerSPN` - The kerberos SPN (Service Principal Name) for the server. Default is MSSQLSvc/host:port.
 * `Workstation ID` - The workstation name (default is the host name)
 * `ApplicationIntent` - Can be given the value `ReadOnly` to initiate a read-only connection to an Availability Group listener. The `database` must be specified when connecting with `Application Intent` set to `ReadOnly`.
 
-### Kerberos Active Directory authentication outside Windows
-The package supports authentication via 3 methods.
-
-* Keytabs - Specify the username, keytab file, the krb5.conf file, and realm.
-
-      authenticator=krb5;server=DatabaseServerName;database=DBName;user id=MyUserName;realm=domain.com;krb5conffile=/etc/krb5.conf;keytabfile=~/MyUserName.keytab
-
-* Credential Cache - Specify the krb5.conf file path and credential cache file path.
-
-      authenticator=krb5;server=DatabaseServerName;database=DBName;krb5conffile=/etc/krb5.conf;krbcache=~/MyUserNameCachedCreds
-
-* Raw credentials - Specity krb5.confg, Username, Password and Realm.
-
-      authenticator=krb5;server=DatabaseServerName;database=DBName;user id=MyUserName;password=foo;realm=comani.com;krb5conffile=/etc/krb5.conf;
-
-### Kerberos Parameters
-
-* `authenticator` - set this to `krb5` to enable kerberos authentication. If this is not present, the default provider would be `ntlm` for unix and `winsspi` for windows.
-* `krb5conffile` (mandatory) - path to kerberos configuration file. 
-* `realm` (required with keytab and raw credentials) - Domain name for kerberos authentication. 
-* `keytabfile` - path to Keytab file.
-* `krbcache` - path to Credential cache.
-* For further information on usage: 
-  * <https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html>
-  * <https://web.mit.edu/kerberos/krb5-1.12/doc/basic/index.html>
-
 ### The connection string can be specified in one of three formats
 
 1. URL: with `sqlserver` scheme. username and password appears before the host. Any instance appears as
@@ -115,17 +89,11 @@ The package supports authentication via 3 methods.
 
     ```
 
-* `sqlserver://username@host/instance?krb5conffile=path/to/file&krbcache=/path/to/cache`
-    * `sqlserver://username@host/instance?krb5conffile=path/to/file&realm=domain.com&keytabfile=/path/to/keytabfile`
-
 2. ADO: `key=value` pairs separated by `;`. Values may not contain `;`, leading and trailing whitespace is ignored.
      Examples:
 
     * `server=localhost\\SQLExpress;user id=sa;database=master;app name=MyAppName`
     * `server=localhost;user id=sa;database=master;app name=MyAppName`
-    * `server=localhost;user id=sa;database=master;app name=MyAppName;krb5conffile=path/to/file;krbcache=path/to/cache;authenticator=krb5`
-    * `server=localhost;user id=sa;database=master;app name=MyAppName;krb5conffile=path/to/file;realm=domain.com;keytabfile=path/to/keytabfile;authenticator=krb5`
-
 
     ADO strings support synonyms for database, app name, user id, and server
     * server <= addr, address, network address, data source
@@ -145,8 +113,6 @@ The package supports authentication via 3 methods.
     * `odbc:server=localhost;user id=sa;password=foo}bar`   // Literal `}`, password is "foo}bar"
     * `odbc:server=localhost;user id=sa;password={foo{bar}` // Literal `{`, password is "foo{bar"
     * `odbc:server=localhost;user id=sa;password={foo}}bar}` // Escaped `} with`}}`, password is "foo}bar"
-    * `odbc:server=localhost;user id=sa;database=master;app name=MyAppName;krb5conffile=path/to/file;krbcache=path/to/cache;authenticator=krb5`
-    * `odbc:server=localhost;user id=sa;database=master;app name=MyAppName;krb5conffile=path/to/file;realm=domain.com;keytabfile=path/to/keytabfile;authenticator=krb5`
 
 ### Azure Active Directory authentication
 
@@ -166,7 +132,6 @@ The credential type is determined by the new `fedauth` connection string paramet
 * `fedauth=ActiveDirectoryDefault` - authenticates using a chained set of credentials. The chain is built from EnvironmentCredential -> ManagedIdentityCredential->AzureCLICredential.  See [DefaultAzureCredential docs](https://github.com/Azure/azure-sdk-for-go/wiki/Set-up-Your-Environment-for-Authentication#configure-defaultazurecredential) for instructions on setting up your host environment to use it. Using this option allows you to have the same connection string in a service deployment as on your interactive development machine.
 * `fedauth=ActiveDirectoryManagedIdentity` or `fedauth=ActiveDirectoryMSI` - authenticates using a system-assigned or user-assigned Azure Managed Identity.
   * `user id=<identity id>` - optional id of user-assigned managed identity. If empty, system-assigned managed identity is used.
-  * `resource id=<resource id>` - optional resource id of user-assigned managed identity.  If empty, system-assigned managed identity or user id are used (if both user id and resource id are provided, resource id will be used)
 * `fedauth=ActiveDirectoryInteractive` - authenticates using credentials acquired from an external web browser. Only suitable for use with human interaction.
   * `applicationclientid=<application id>` - This guid identifies an Azure Active Directory enterprise application that the AAD admin has approved for accessing Azure SQL database resources in the tenant. This driver does not have an associated application id of its own.
 
@@ -177,7 +142,7 @@ import (
   "net/url"
 
   // Import the Azure AD driver module (also imports the regular driver package)
-  "github.com/microsoft/go-mssqldb/azuread"
+  "github.com/denisenkom/go-mssqldb/azuread"
 )
 
 func ConnectWithMSI() (*sql.DB, error) {
@@ -317,19 +282,6 @@ are supported:
 * "github.com/golang-sql/civil".Time -> time
 * mssql.TVP -> Table Value Parameter (TDS version dependent)
 
-Using an `int` parameter will send a 4 byte value (int) from a 32bit app and an 8 byte value (bigint) from a 64bit app. 
-To make sure your integer parameter matches the size of the SQL parameter, use the appropriate sized type like `int32` or `int8`.
-
-```go
-// If this is passed directly as a parameter, 
-// the SQL parameter generated would be nvarchar
-name := "Bob"
-// If the user_name is defined as varchar,
-// it needs to be converted like this:
-db.QueryContext(ctx, `select * from t2 where user_name = @p1;`, mssql.VarChar(name))
-// Note: Mismatched data types on table and parameter may cause long running queries
-```
-
 ## Important Notes
 
 * [LastInsertId](https://golang.org/pkg/database/sql/#Result.LastInsertId) should
@@ -338,9 +290,9 @@ db.QueryContext(ctx, `select * from t2 where user_name = @p1;`, mssql.VarChar(na
  or add a `select ID = convert(bigint, SCOPE_IDENTITY());` to the end of your
  query (ref [SCOPE_IDENTITY](https://docs.microsoft.com/en-us/sql/t-sql/functions/scope-identity-transact-sql)).
  This will ensure you are getting the correct ID and will prevent a network round trip.
-* [NewConnector](https://godoc.org/github.com/microsoft/go-mssqldb#NewConnector)
+* [NewConnector](https://godoc.org/github.com/denisenkom/go-mssqldb#NewConnector)
     may be used with [OpenDB](https://golang.org/pkg/database/sql/#OpenDB).
-* [Connector.SessionInitSQL](https://godoc.org/github.com/microsoft/go-mssqldb#Connector.SessionInitSQL)
+* [Connector.SessionInitSQL](https://godoc.org/github.com/denisenkom/go-mssqldb#Connector.SessionInitSQL)
  may be set to set any driver specific session settings after the session
  has been reset. If empty the session will still be reset but use the database
  defaults in Go1.10+.
@@ -357,9 +309,6 @@ db.QueryContext(ctx, `select * from t2 where user_name = @p1;`, mssql.VarChar(na
 * Supports Single-Sign-On on Windows
 * Supports connections to AlwaysOn Availability Group listeners, including re-direction to read-only replicas.
 * Supports query notifications
-* Supports Kerberos Authentication
-* Pluggable Dialer implementations through `msdsn.ProtocolParsers` and `msdsn.ProtocolDialers`
-* A `namedpipe` package to support connections using named pipes on Windows
 
 ## Tests
 
@@ -399,20 +348,3 @@ Use the native "@Name" parameters instead with the "sqlserver" driver name.
 To fix SQL Server 2008 R2 issue, install SQL Server 2008 R2 Service Pack 2.
 To fix SQL Server 2008 issue, install Microsoft SQL Server 2008 Service Pack 3 and Cumulative update package 3 for SQL Server 2008 SP3.
 More information: <http://support.microsoft.com/kb/2653857>
-
-
-# Contributing
-This project is a fork of [https://github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb) and welcomes new and previous contributors. For more informaton on contributing to this project, please see [Contributing](./CONTRIBUTING.md).
-
-For more information on the roadmap for go-mssqldb, [project plans](https://github.com/microsoft/go-mssqldb/projects) are available for viewing and discussion.
-
-
-# Microsoft Open Source Code of Conduct
-
-This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
-
-Resources:
-
-- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
-- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
-- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
diff --git a/SECURITY.md b/SECURITY.md
deleted file mode 100644
index f7b8998..0000000
--- a/SECURITY.md
+++ /dev/null
@@ -1,41 +0,0 @@
-<!-- BEGIN MICROSOFT SECURITY.MD V0.0.5 BLOCK -->
-
-## Security
-
-Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
-
-If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below.
-
-## Reporting Security Issues
-
-**Please do not report security vulnerabilities through public GitHub issues.**
-
-Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
-
-If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com).  If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
-
-You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 
-
-Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
-
-  * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
-  * Full paths of source file(s) related to the manifestation of the issue
-  * The location of the affected source code (tag/branch/commit or direct URL)
-  * Any special configuration required to reproduce the issue
-  * Step-by-step instructions to reproduce the issue
-  * Proof-of-concept or exploit code (if possible)
-  * Impact of the issue, including how an attacker might exploit the issue
-
-This information will help us triage your report more quickly.
-
-If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
-
-## Preferred Languages
-
-We prefer all communications to be in English.
-
-## Policy
-
-Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
-
-<!-- END MICROSOFT SECURITY.MD BLOCK -->
\ No newline at end of file
diff --git a/appveyor.yml b/appveyor.yml
index c57f868..c03f375 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -3,7 +3,7 @@ version: 1.0.{build}
 image:
   - Visual Studio 2015
 
-clone_folder: c:\gopath\src\github.com\microsoft\go-mssqldb
+clone_folder: c:\gopath\src\github.com\denisenkom\go-mssqldb
 
 environment:
   GOPATH: c:\gopath
@@ -12,9 +12,11 @@ environment:
   SQLPASSWORD: Password12!
   DATABASE: test
   GOVERSION: 113
-  RACE: -race -cpu 4
-  TAGS:
   matrix:
+    - GOVERSION: 18
+      SQLINSTANCE: SQL2017
+    - GOVERSION: 19
+      SQLINSTANCE: SQL2017
     - GOVERSION: 110
       SQLINSTANCE: SQL2017
     - GOVERSION: 111
@@ -40,19 +42,7 @@ environment:
     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
       GOVERSION: 116
       SQLINSTANCE: SQL2017
-    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
-      GOVERSION: 117
-      SQLINSTANCE: SQL2017
-    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
-      GOVERSION: 118
-      SQLINSTANCE: SQL2017
-    - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
-      GOVERSION: 118-x86
-      SQLINSTANCE: SQL2017
-      GOARCH: 386
-      RACE:
-      PROTOCOL: np
-      TAGS: -tags np
+
 install:
   - set GOROOT=c:\go%GOVERSION%
   - set PATH=%GOPATH%\bin;%GOROOT%\bin;%PATH%
@@ -60,7 +50,6 @@ install:
   - go env
   - go get -u github.com/golang-sql/civil
   - go get -u github.com/golang-sql/sqlexp
-  - go get -u golang.org/x/crypto/md4
 
 build_script:
   - go build
@@ -68,24 +57,13 @@ build_script:
 before_test:
   # setup SQL Server
   - ps: |
-      [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null
-      [reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.SqlWmiManagement") | Out-Null
-      $smo = 'Microsoft.SqlServer.Management.Smo.'
-      $wmi = new-object ($smo + 'Wmi.ManagedComputer')
-      $serverName = $env:COMPUTERNAME
       $instanceName = $env:SQLINSTANCE
-      # Enable named pipes
-      $uri = "ManagedComputer[@Name='$serverName']/ServerInstance[@Name='$instanceName']/ServerProtocol[@Name='Np']"
-      $Np = $wmi.GetSmoObject($uri)
-      $Np.IsEnabled = $true
-      $Np.Alter()
-      Start-Service "SQLBrowser"
       Start-Service "MSSQL`$$instanceName"
-      Start-Sleep -Seconds 10
+      Start-Service "SQLBrowser"
   - sqlcmd -S "(local)\%SQLINSTANCE%" -Q "Use [master]; CREATE DATABASE test;"
-  - sqlcmd -S "np:.\%SQLINSTANCE%" -h -1 -Q "set nocount on; Select @@version"
+  - sqlcmd -S "(local)\%SQLINSTANCE%" -h -1 -Q "set nocount on; Select @@version"
   - pip install codecov
 
 test_script:
-  - go test %RACE% -coverprofile=coverage.txt -covermode=atomic %TAGS%
+  - go test -race -cpu 4 -coverprofile=coverage.txt -covermode=atomic
   - codecov -f coverage.txt
diff --git a/auth_unix.go b/auth_unix.go
deleted file mode 100644
index 79be775..0000000
--- a/auth_unix.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// +build !windows
-
-package mssql
-
-import (
-	"github.com/microsoft/go-mssqldb/integratedauth"
-	// nolint importing the ntlm package causes it to be registered as an available authentication provider
-	_ "github.com/microsoft/go-mssqldb/integratedauth/ntlm"
-)
-
-func init() {
-	// we set the default authentication provider name here, rather than within each imported package,
-	// to force a known default. Go will order execution of init() calls but it is better to be explicit.
-	integratedauth.DefaultProviderName = "ntlm"
-}
diff --git a/auth_windows.go b/auth_windows.go
deleted file mode 100644
index 8ed454f..0000000
--- a/auth_windows.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// +build windows
-
-package mssql
-
-import (
-	"github.com/microsoft/go-mssqldb/integratedauth"
-
-	// nolint importing the ntlm package causes it to be registered as an available authentication provider
-	_ "github.com/microsoft/go-mssqldb/integratedauth/ntlm"
-	// nolint importing the winsspi package causes it to be registered as an available authentication provider
-	_ "github.com/microsoft/go-mssqldb/integratedauth/winsspi"
-)
-
-func init() {
-	// we set the default authentication provider name here, rather than within each imported package,
-	// to force a known default. Go will order execution of init() calls but it is better to be explicit.
-	integratedauth.DefaultProviderName = "winsspi"
-}
diff --git a/azuread/configuration.go b/azuread/configuration.go
index e3c2eb7..c205b40 100644
--- a/azuread/configuration.go
+++ b/azuread/configuration.go
@@ -1,213 +1,203 @@
-//go:build go1.18
-// +build go1.18
-
-package azuread
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"os"
-	"strings"
-
-	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
-	"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
-	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
-	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
-	mssql "github.com/microsoft/go-mssqldb"
-	"github.com/microsoft/go-mssqldb/msdsn"
-)
-
-const (
-	ActiveDirectoryDefault     = "ActiveDirectoryDefault"
-	ActiveDirectoryIntegrated  = "ActiveDirectoryIntegrated"
-	ActiveDirectoryPassword    = "ActiveDirectoryPassword"
-	ActiveDirectoryInteractive = "ActiveDirectoryInteractive"
-	// ActiveDirectoryMSI is a synonym for ActiveDirectoryManagedIdentity
-	ActiveDirectoryMSI             = "ActiveDirectoryMSI"
-	ActiveDirectoryManagedIdentity = "ActiveDirectoryManagedIdentity"
-	// ActiveDirectoryApplication is a synonym for ActiveDirectoryServicePrincipal
-	ActiveDirectoryApplication      = "ActiveDirectoryApplication"
-	ActiveDirectoryServicePrincipal = "ActiveDirectoryServicePrincipal"
-	scopeDefaultSuffix              = "/.default"
-)
-
-type azureFedAuthConfig struct {
-	adalWorkflow byte
-	mssqlConfig  msdsn.Config
-	// The detected federated authentication library
-	fedAuthLibrary  int
-	fedAuthWorkflow string
-	// Service principal logins
-	clientID        string
-	tenantID        string
-	clientSecret    string
-	certificatePath string
-	resourceID      string
-
-	// AD password/managed identity/interactive
-	user                string
-	password            string
-	applicationClientID string
-}
-
-// parse returns a config based on an msdsn-style connection string
-func parse(dsn string) (*azureFedAuthConfig, error) {
-	mssqlConfig, err := msdsn.Parse(dsn)
-	if err != nil {
-		return nil, err
-	}
-	config := &azureFedAuthConfig{
-		fedAuthLibrary: mssql.FedAuthLibraryReserved,
-		mssqlConfig:    mssqlConfig,
-	}
-
-	err = config.validateParameters(mssqlConfig.Parameters)
-	if err != nil {
-		return nil, err
-	}
-
-	return config, nil
-}
-
-func (p *azureFedAuthConfig) validateParameters(params map[string]string) error {
-
-	fedAuthWorkflow, _ := params["fedauth"]
-	if fedAuthWorkflow == "" {
-		return nil
-	}
-
-	p.fedAuthLibrary = mssql.FedAuthLibraryADAL
-
-	p.applicationClientID, _ = params["applicationclientid"]
-
-	switch {
-	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryPassword):
-		if p.applicationClientID == "" {
-			return errors.New("applicationclientid parameter is required for " + ActiveDirectoryPassword)
-		}
-		p.adalWorkflow = mssql.FedAuthADALWorkflowPassword
-		p.user, _ = params["user id"]
-		p.password, _ = params["password"]
-	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryIntegrated):
-		// Active Directory Integrated authentication is not fully supported:
-		// you can only use this by also implementing an a token provider
-		// and supplying it via ActiveDirectoryTokenProvider in the Connection.
-		p.adalWorkflow = mssql.FedAuthADALWorkflowIntegrated
-	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryManagedIdentity) || strings.EqualFold(fedAuthWorkflow, ActiveDirectoryMSI):
-		// When using MSI, to request a specific client ID or user-assigned identity,
-		// provide the ID in the "user id" parameter
-		p.adalWorkflow = mssql.FedAuthADALWorkflowMSI
-		p.resourceID, _ = params["resource id"]
-		p.clientID, _ = splitTenantAndClientID(params["user id"])
-	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryApplication) || strings.EqualFold(fedAuthWorkflow, ActiveDirectoryServicePrincipal):
-		p.adalWorkflow = mssql.FedAuthADALWorkflowPassword
-		// Split the clientID@tenantID format
-		// If no tenant is provided we'll use the one from the server
-		p.clientID, p.tenantID = splitTenantAndClientID(params["user id"])
-		if p.clientID == "" {
-			return errors.New("Must provide 'client id[@tenant id]' as username parameter when using ActiveDirectoryApplication authentication")
-		}
-
-		p.clientSecret, _ = params["password"]
-
-		p.certificatePath, _ = params["clientcertpath"]
-
-		if p.certificatePath == "" && p.clientSecret == "" {
-			return errors.New("Must provide 'password' parameter when using ActiveDirectoryApplication authentication without cert/key credentials")
-		}
-	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryDefault):
-		p.adalWorkflow = mssql.FedAuthADALWorkflowPassword
-	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryInteractive):
-		if p.applicationClientID == "" {
-			return errors.New("applicationclientid parameter is required for " + ActiveDirectoryInteractive)
-		}
-		p.adalWorkflow = mssql.FedAuthADALWorkflowPassword
-		// user is an optional login hint
-		p.user, _ = params["user id"]
-		// we don't really have a password but we need to use some value.
-		p.adalWorkflow = mssql.FedAuthADALWorkflowPassword
-
-	default:
-		return fmt.Errorf("Invalid federated authentication type '%s': expected one of %+v",
-			fedAuthWorkflow,
-			[]string{ActiveDirectoryApplication, ActiveDirectoryServicePrincipal, ActiveDirectoryDefault, ActiveDirectoryIntegrated, ActiveDirectoryInteractive, ActiveDirectoryManagedIdentity, ActiveDirectoryMSI, ActiveDirectoryPassword})
-	}
-	p.fedAuthWorkflow = fedAuthWorkflow
-	return nil
-}
-
-func splitTenantAndClientID(user string) (string, string) {
-	// Split the user name into client id and tenant id at the @ symbol
-	at := strings.IndexRune(user, '@')
-	if at < 1 || at >= (len(user)-1) {
-		return user, ""
-	}
-
-	return user[0:at], user[at+1:]
-}
-
-func splitAuthorityAndTenant(authorityUrl string) (string, string) {
-	separatorIndex := strings.LastIndex(authorityUrl, "/")
-	tenant := authorityUrl[separatorIndex+1:]
-	authority := authorityUrl[:separatorIndex]
-	return authority, tenant
-}
-
-func (p *azureFedAuthConfig) provideActiveDirectoryToken(ctx context.Context, serverSPN, stsURL string) (string, error) {
-	var cred azcore.TokenCredential
-	var err error
-	authority, tenant := splitAuthorityAndTenant(stsURL)
-	// client secret connection strings may override the server tenant
-	if p.tenantID != "" {
-		tenant = p.tenantID
-	}
-	scope := stsURL
-	if !strings.HasSuffix(serverSPN, scopeDefaultSuffix) {
-		scope = strings.TrimRight(serverSPN, "/") + scopeDefaultSuffix
-	}
-
-	switch p.fedAuthWorkflow {
-	case ActiveDirectoryServicePrincipal, ActiveDirectoryApplication:
-		switch {
-		case p.certificatePath != "":
-			certData, err := os.ReadFile(p.certificatePath)
-			if err != nil {
-				certs, key, err := azidentity.ParseCertificates(certData, []byte(p.clientSecret))
-				if err != nil {
-					cred, err = azidentity.NewClientCertificateCredential(tenant, p.clientID, certs, key, nil)
-				}
-			}
-		default:
-			cred, err = azidentity.NewClientSecretCredential(tenant, p.clientID, p.clientSecret, nil)
-		}
-	case ActiveDirectoryPassword:
-		cred, err = azidentity.NewUsernamePasswordCredential(tenant, p.applicationClientID, p.user, p.password, nil)
-	case ActiveDirectoryMSI, ActiveDirectoryManagedIdentity:
-		if p.resourceID != "" {
-			cred, err = azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{ID: azidentity.ResourceID(p.resourceID)})
-		} else if p.clientID != "" {
-			cred, err = azidentity.NewManagedIdentityCredential(&azidentity.ManagedIdentityCredentialOptions{ID: azidentity.ClientID(p.clientID)})
-		} else {
-			cred, err = azidentity.NewManagedIdentityCredential(nil)
-		}
-	case ActiveDirectoryInteractive:
-		c := cloud.Configuration{ActiveDirectoryAuthorityHost: authority}
-		config := azcore.ClientOptions{Cloud: c}
-		cred, err = azidentity.NewInteractiveBrowserCredential(&azidentity.InteractiveBrowserCredentialOptions{ClientOptions: config, ClientID: p.applicationClientID})
-
-	default:
-		// Integrated just uses Default until azidentity adds Windows-specific authentication
-		cred, err = azidentity.NewDefaultAzureCredential(nil)
-	}
-
-	if err != nil {
-		return "", err
-	}
-	opts := policy.TokenRequestOptions{Scopes: []string{scope}}
-	tk, err := cred.GetToken(ctx, opts)
-	if err != nil {
-		return "", err
-	}
-	return tk.Token, err
-}
+package azuread
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"strings"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
+	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
+
+	mssql "github.com/denisenkom/go-mssqldb"
+	"github.com/denisenkom/go-mssqldb/msdsn"
+)
+
+const (
+	ActiveDirectoryDefault     = "ActiveDirectoryDefault"
+	ActiveDirectoryIntegrated  = "ActiveDirectoryIntegrated"
+	ActiveDirectoryPassword    = "ActiveDirectoryPassword"
+	ActiveDirectoryInteractive = "ActiveDirectoryInteractive"
+	// ActiveDirectoryMSI is a synonym for ActiveDirectoryManagedIdentity
+	ActiveDirectoryMSI             = "ActiveDirectoryMSI"
+	ActiveDirectoryManagedIdentity = "ActiveDirectoryManagedIdentity"
+	// ActiveDirectoryApplication is a synonym for ActiveDirectoryServicePrincipal
+	ActiveDirectoryApplication                 = "ActiveDirectoryApplication"
+	ActiveDirectoryServicePrincipal            = "ActiveDirectoryServicePrincipal"
+	ActiveDirectoryServicePrincipalAccessToken = "ActiveDirectoryServicePrincipalAccessToken"
+	scopeDefaultSuffix                         = "/.default"
+)
+
+type azureFedAuthConfig struct {
+	adalWorkflow byte
+	mssqlConfig  msdsn.Config
+	// The detected federated authentication library
+	fedAuthLibrary  int
+	fedAuthWorkflow string
+	// Service principal logins
+	clientID        string
+	tenantID        string
+	clientSecret    string
+	certificatePath string
+
+	// AD password/managed identity/interactive
+	user                string
+	password            string
+	applicationClientID string
+}
+
+// parse returns a config based on an msdsn-style connection string
+func parse(dsn string) (*azureFedAuthConfig, error) {
+	mssqlConfig, params, err := msdsn.Parse(dsn)
+	if err != nil {
+		return nil, err
+	}
+	config := &azureFedAuthConfig{
+		fedAuthLibrary: mssql.FedAuthLibraryReserved,
+		mssqlConfig:    mssqlConfig,
+	}
+
+	err = config.validateParameters(params)
+	if err != nil {
+		return nil, err
+	}
+
+	return config, nil
+}
+
+func (p *azureFedAuthConfig) validateParameters(params map[string]string) error {
+
+	fedAuthWorkflow, _ := params["fedauth"]
+	if fedAuthWorkflow == "" {
+		return nil
+	}
+
+	p.fedAuthLibrary = mssql.FedAuthLibraryADAL
+
+	p.applicationClientID, _ = params["applicationclientid"]
+
+	switch {
+	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryPassword):
+		if p.applicationClientID == "" {
+			return errors.New("applicationclientid parameter is required for " + ActiveDirectoryPassword)
+		}
+		p.adalWorkflow = mssql.FedAuthADALWorkflowPassword
+		p.user, _ = params["user id"]
+		p.password, _ = params["password"]
+	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryIntegrated):
+		// Active Directory Integrated authentication is not fully supported:
+		// you can only use this by also implementing an a token provider
+		// and supplying it via ActiveDirectoryTokenProvider in the Connection.
+		p.adalWorkflow = mssql.FedAuthADALWorkflowIntegrated
+	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryManagedIdentity) || strings.EqualFold(fedAuthWorkflow, ActiveDirectoryMSI):
+		// When using MSI, to request a specific client ID or user-assigned identity,
+		// provide the ID in the "user id" parameter
+		p.adalWorkflow = mssql.FedAuthADALWorkflowMSI
+		p.clientID, _ = splitTenantAndClientID(params["user id"])
+	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryApplication) || strings.EqualFold(fedAuthWorkflow, ActiveDirectoryServicePrincipal):
+		p.adalWorkflow = mssql.FedAuthADALWorkflowPassword
+		// Split the clientID@tenantID format
+		// If no tenant is provided we'll use the one from the server
+		p.clientID, p.tenantID = splitTenantAndClientID(params["user id"])
+		if p.clientID == "" {
+			return errors.New("Must provide 'client id[@tenant id]' as username parameter when using ActiveDirectoryApplication authentication")
+		}
+
+		p.clientSecret, _ = params["password"]
+
+		p.certificatePath, _ = params["clientcertpath"]
+
+		if p.certificatePath == "" && p.clientSecret == "" {
+			return errors.New("Must provide 'password' parameter when using ActiveDirectoryApplication authentication without cert/key credentials")
+		}
+	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryDefault):
+		p.adalWorkflow = mssql.FedAuthADALWorkflowPassword
+	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryInteractive):
+		if p.applicationClientID == "" {
+			return errors.New("applicationclientid parameter is required for " + ActiveDirectoryInteractive)
+		}
+		p.adalWorkflow = mssql.FedAuthADALWorkflowPassword
+		// user is an optional login hint
+		p.user, _ = params["user id"]
+		// we don't really have a password but we need to use some value.
+		p.adalWorkflow = mssql.FedAuthADALWorkflowPassword
+	case strings.EqualFold(fedAuthWorkflow, ActiveDirectoryServicePrincipalAccessToken):
+		p.fedAuthLibrary = mssql.FedAuthLibrarySecurityToken
+		p.adalWorkflow = mssql.FedAuthADALWorkflowNone
+		p.password, _ = params["password"]
+
+		if p.password == "" {
+			return errors.New("Must provide 'password' parameter when using ActiveDirectoryApplicationAuthToken authentication")
+		}
+	default:
+		return fmt.Errorf("Invalid federated authentication type '%s': expected one of %+v",
+			fedAuthWorkflow,
+			[]string{ActiveDirectoryApplication, ActiveDirectoryServicePrincipal, ActiveDirectoryDefault, ActiveDirectoryIntegrated, ActiveDirectoryInteractive, ActiveDirectoryManagedIdentity, ActiveDirectoryMSI, ActiveDirectoryPassword})
+	}
+	p.fedAuthWorkflow = fedAuthWorkflow
+	return nil
+}
+
+func splitTenantAndClientID(user string) (string, string) {
+	// Split the user name into client id and tenant id at the @ symbol
+	at := strings.IndexRune(user, '@')
+	if at < 1 || at >= (len(user)-1) {
+		return user, ""
+	}
+
+	return user[0:at], user[at+1:]
+}
+
+func splitAuthorityAndTenant(authorityUrl string) (string, string) {
+	separatorIndex := strings.LastIndex(authorityUrl, "/")
+	tenant := authorityUrl[separatorIndex+1:]
+	authority := authorityUrl[:separatorIndex]
+	return authority, tenant
+}
+
+func (p *azureFedAuthConfig) provideActiveDirectoryToken(ctx context.Context, serverSPN, stsURL string) (string, error) {
+	var cred azcore.TokenCredential
+	var err error
+	authority, tenant := splitAuthorityAndTenant(stsURL)
+	// client secret connection strings may override the server tenant
+	if p.tenantID != "" {
+		tenant = p.tenantID
+	}
+	scope := stsURL
+	if !strings.HasSuffix(serverSPN, scopeDefaultSuffix) {
+		scope = strings.TrimRight(serverSPN, "/") + scopeDefaultSuffix
+	}
+
+	switch p.fedAuthWorkflow {
+	case ActiveDirectoryServicePrincipal, ActiveDirectoryApplication:
+		switch {
+		case p.certificatePath != "":
+			cred, err = azidentity.NewClientCertificateCredential(tenant, p.clientID, p.certificatePath, &azidentity.ClientCertificateCredentialOptions{Password: p.clientSecret})
+		default:
+			cred, err = azidentity.NewClientSecretCredential(tenant, p.clientID, p.clientSecret, nil)
+		}
+	case ActiveDirectoryServicePrincipalAccessToken:
+		return p.password, nil
+	case ActiveDirectoryPassword:
+		cred, err = azidentity.NewUsernamePasswordCredential(tenant, p.applicationClientID, p.user, p.password, nil)
+	case ActiveDirectoryMSI, ActiveDirectoryManagedIdentity:
+		cred, err = azidentity.NewManagedIdentityCredential(p.clientID, nil)
+	case ActiveDirectoryInteractive:
+		cred, err = azidentity.NewInteractiveBrowserCredential(&azidentity.InteractiveBrowserCredentialOptions{AuthorityHost: authority, ClientID: p.applicationClientID})
+
+	default:
+		// Integrated just uses Default until azidentity adds Windows-specific authentication
+		cred, err = azidentity.NewDefaultAzureCredential(nil)
+	}
+
+	if err != nil {
+		return "", err
+	}
+	opts := policy.TokenRequestOptions{Scopes: []string{scope}}
+	tk, err := cred.GetToken(ctx, opts)
+	if err != nil {
+		return "", err
+	}
+	return tk.Token, err
+}
diff --git a/azuread/driver.go b/azuread/driver.go
index 3320d7b..e93d4fb 100644
--- a/azuread/driver.go
+++ b/azuread/driver.go
@@ -1,57 +1,63 @@
-//go:build go1.18
-// +build go1.18
-
-package azuread
-
-import (
-	"context"
-	"database/sql"
-	"database/sql/driver"
-
-	mssql "github.com/microsoft/go-mssqldb"
-)
-
-// DriverName is the name used to register the driver
-const DriverName = "azuresql"
-
-func init() {
-	sql.Register(DriverName, &Driver{})
-}
-
-// Driver wraps the underlying MSSQL driver, but configures the Azure AD token provider
-type Driver struct {
-}
-
-// Open returns a new connection to the database.
-func (d *Driver) Open(dsn string) (driver.Conn, error) {
-	c, err := NewConnector(dsn)
-	if err != nil {
-		return nil, err
-	}
-
-	return c.Connect(context.Background())
-}
-
-// NewConnector creates a new connector from a DSN.
-// The returned connector may be used with sql.OpenDB.
-func NewConnector(dsn string) (*mssql.Connector, error) {
-
-	config, err := parse(dsn)
-	if err != nil {
-		return nil, err
-	}
-	return newConnectorConfig(config)
-}
-
-// newConnectorConfig creates a Connector from config.
-func newConnectorConfig(config *azureFedAuthConfig) (*mssql.Connector, error) {
-	if config.fedAuthLibrary == mssql.FedAuthLibraryADAL {
-		return mssql.NewActiveDirectoryTokenConnector(
-			config.mssqlConfig, config.adalWorkflow,
-			func(ctx context.Context, serverSPN, stsURL string) (string, error) {
-				return config.provideActiveDirectoryToken(ctx, serverSPN, stsURL)
-			},
-		)
-	}
-	return mssql.NewConnectorConfig(config.mssqlConfig), nil
-}
+package azuread
+
+import (
+	"context"
+	"database/sql"
+	"database/sql/driver"
+
+	mssql "github.com/denisenkom/go-mssqldb"
+)
+
+// DriverName is the name used to register the driver
+const DriverName = "azuresql"
+
+func init() {
+	sql.Register(DriverName, &Driver{})
+}
+
+// Driver wraps the underlying MSSQL driver, but configures the Azure AD token provider
+type Driver struct {
+}
+
+// Open returns a new connection to the database.
+func (d *Driver) Open(dsn string) (driver.Conn, error) {
+	c, err := NewConnector(dsn)
+	if err != nil {
+		return nil, err
+	}
+
+	return c.Connect(context.Background())
+}
+
+// NewConnector creates a new connector from a DSN.
+// The returned connector may be used with sql.OpenDB.
+func NewConnector(dsn string) (*mssql.Connector, error) {
+
+	config, err := parse(dsn)
+	if err != nil {
+		return nil, err
+	}
+	return newConnectorConfig(config)
+}
+
+// newConnectorConfig creates a Connector from config.
+func newConnectorConfig(config *azureFedAuthConfig) (*mssql.Connector, error) {
+	switch config.fedAuthLibrary {
+	case mssql.FedAuthLibraryADAL:
+		return mssql.NewActiveDirectoryTokenConnector(
+			config.mssqlConfig, config.adalWorkflow,
+			func(ctx context.Context, serverSPN, stsURL string) (string, error) {
+				return config.provideActiveDirectoryToken(ctx, serverSPN, stsURL)
+			},
+		)
+	case mssql.FedAuthLibrarySecurityToken:
+		return mssql.NewSecurityTokenConnector(
+			config.mssqlConfig,
+			func(ctx context.Context) (string, error) {
+				return config.password, nil
+			},
+		)
+	default:
+		return mssql.NewConnectorConfig(config.mssqlConfig), nil
+	}
+}
diff --git a/buf.go b/buf.go
index 6866342..051d7ba 100644
--- a/buf.go
+++ b/buf.go
@@ -4,7 +4,6 @@ import (
 	"encoding/binary"
 	"errors"
 	"io"
-	"sync"
 )
 
 type packetType uint8
@@ -18,16 +17,6 @@ type header struct {
 	Pad        uint8
 }
 
-// bufpool provides buffers which are used for reading and writing in the tdsBuffer instances
-var bufpool = sync.Pool{
-	New: func() interface{} {
-		b := make([]byte, 1<<16)
-		// If the return value is not a pointer, any conversion from interface{} will
-		// involve an allocation.
-		return &b
-	},
-}
-
 // tdsBuffer reads and writes TDS packets of data to the transport.
 // The write and read buffers are separate to make sending attn signals
 // possible without locks. Currently attn signals are only sent during
@@ -37,9 +26,6 @@ type tdsBuffer struct {
 
 	packetSize int
 
-	// bufClose is responsible for returning the buffer back to the pool
-	bufClose func()
-
 	// Write fields.
 	wbuf        []byte
 	wpos        int
@@ -60,15 +46,10 @@ type tdsBuffer struct {
 }
 
 func newTdsBuffer(bufsize uint16, transport io.ReadWriteCloser) *tdsBuffer {
-
-	// pull an existing buf if one is available or get and add a new buf to the bufpool
-	buf := bufpool.Get().(*[]byte)
-
 	return &tdsBuffer{
 		packetSize: int(bufsize),
-		wbuf:       (*buf)[:1<<15],
-		rbuf:       (*buf)[1<<15:],
-		bufClose:   func() { bufpool.Put(buf) },
+		wbuf:       make([]byte, bufsize),
+		rbuf:       make([]byte, bufsize),
 		rpos:       8,
 		transport:  transport,
 	}
@@ -220,27 +201,16 @@ func (r *tdsBuffer) byte() byte {
 }
 
 func (r *tdsBuffer) ReadFull(buf []byte) {
-	_, err := io.ReadFull(r, buf)
+	_, err := io.ReadFull(r, buf[:])
 	if err != nil {
 		badStreamPanic(err)
 	}
 }
 
 func (r *tdsBuffer) uint64() uint64 {
-	// have we got enough room in the buffer to read 8 bytes, if not, do a ReadFull, else read directly from r.rbuf
-	if r.rpos+7 >= r.rsize {
-		var buf [8]byte
-		r.ReadFull(buf[:])
-
-		return uint64(buf[0]) | uint64(buf[1])<<8 | uint64(buf[2])<<16 | uint64(buf[3])<<24 |
-			uint64(buf[4])<<32 | uint64(buf[5])<<40 | uint64(buf[6])<<48 | uint64(buf[7])<<56
-	}
-
-	res := uint64(r.rbuf[r.rpos]) | uint64(r.rbuf[r.rpos+1])<<8 | uint64(r.rbuf[r.rpos+2])<<16 | uint64(r.rbuf[r.rpos+3])<<24 |
-		uint64(r.rbuf[r.rpos+4])<<32 | uint64(r.rbuf[r.rpos+5])<<40 | uint64(r.rbuf[r.rpos+6])<<48 | uint64(r.rbuf[r.rpos+7])<<56
-
-	r.rpos += 8
-	return res
+	var buf [8]byte
+	r.ReadFull(buf[:])
+	return binary.LittleEndian.Uint64(buf[:])
 }
 
 func (r *tdsBuffer) int32() int32 {
@@ -248,29 +218,15 @@ func (r *tdsBuffer) int32() int32 {
 }
 
 func (r *tdsBuffer) uint32() uint32 {
-	// have we got enough room in the buffer to read 4 bytes, if not, do a ReadFull, else read directly from r.rbuf
-	if r.rpos+3 >= r.rsize {
-		var buf [4]byte
-		r.ReadFull(buf[:])
-		return uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24
-	}
-
-	res := uint32(r.rbuf[r.rpos]) | uint32(r.rbuf[r.rpos+1])<<8 | uint32(r.rbuf[r.rpos+2])<<16 | uint32(r.rbuf[r.rpos+3])<<24
-	r.rpos += 4
-	return res
+	var buf [4]byte
+	r.ReadFull(buf[:])
+	return binary.LittleEndian.Uint32(buf[:])
 }
 
 func (r *tdsBuffer) uint16() uint16 {
-	// have we got enough room in the buffer to read 2 bytes, if not, do a ReadFull, else read directly from r.rbuf
-	if r.rpos+1 >= r.rsize {
-		var buf [2]byte
-		r.ReadFull(buf[:])
-		return uint16(buf[0]) | uint16(buf[1])<<8
-	}
-
-	res := uint16(r.rbuf[r.rpos]) | uint16(r.rbuf[r.rpos+1])<<8
-	r.rpos += 2
-	return res
+	var buf [2]byte
+	r.ReadFull(buf[:])
+	return binary.LittleEndian.Uint16(buf[:])
 }
 
 func (r *tdsBuffer) BVarChar() string {
diff --git a/bulkcopy.go b/bulkcopy.go
index 97edb7b..f6cf97a 100644
--- a/bulkcopy.go
+++ b/bulkcopy.go
@@ -11,8 +11,8 @@ import (
 	"strings"
 	"time"
 
-	"github.com/microsoft/go-mssqldb/internal/decimal"
-	"github.com/microsoft/go-mssqldb/msdsn"
+	"github.com/denisenkom/go-mssqldb/internal/decimal"
+	"github.com/denisenkom/go-mssqldb/msdsn"
 )
 
 type Bulk struct {
@@ -381,14 +381,6 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error)
 			res.buffer = str2ucs2(val)
 		case int64:
 			res.buffer = []byte(strconv.FormatInt(val, 10))
-		case int:
-			res.buffer = []byte(strconv.FormatInt(int64(val), 10))
-		case int8:
-			res.buffer = []byte(strconv.FormatInt(int64(val), 10))
-		case int32:
-			res.buffer = []byte(strconv.FormatInt(int64(val), 10))
-		case int16:
-			res.buffer = []byte(strconv.FormatInt(int64(val), 10))
 		case []byte:
 			res.buffer = val
 		default:
@@ -403,14 +395,6 @@ func (b *Bulk) makeParam(val DataValue, col columnStruct) (res param, err error)
 			res.buffer = []byte(val)
 		case []byte:
 			res.buffer = val
-		case int:
-			res.buffer = []byte(strconv.FormatInt(int64(val), 10))
-		case int8:
-			res.buffer = []byte(strconv.FormatInt(int64(val), 10))
-		case int16:
-			res.buffer = []byte(strconv.FormatInt(int64(val), 10))
-		case int32:
-			res.buffer = []byte(strconv.FormatInt(int64(val), 10))
 		case int64:
 			res.buffer = []byte(strconv.FormatInt(val, 10))
 		default:
diff --git a/doc/how-to-perform-bulk-imports.md b/doc/how-to-perform-bulk-imports.md
index 3ac3dcc..f8c0a3a 100644
--- a/doc/how-to-perform-bulk-imports.md
+++ b/doc/how-to-perform-bulk-imports.md
@@ -5,7 +5,7 @@ To use the bulk imports feature in go-mssqldb, you need to import the sql and go
 ```
 import (
     "database/sql"
-    "github.com/microsoft/go-mssqldb"
+    "github.com/denisenkom/go-mssqldb"
 )
 ```
 
diff --git a/doc/how-to-use-newconnector.md b/doc/how-to-use-newconnector.md
index cd89414..0273d89 100644
--- a/doc/how-to-use-newconnector.md
+++ b/doc/how-to-use-newconnector.md
@@ -7,7 +7,7 @@ To use the Connector type, first you need to import the sql and go-mssqldb packa
 ```
 import (
   "database/sql"
-  "github.com/microsoft/go-mssqldb"
+  "github.com/denisenkom/go-mssqldb"
 )
 ```
 
diff --git a/examples/azuread-accesstoken/go.mod b/examples/azuread-accesstoken/go.mod
index cee1784..eb113f3 100644
--- a/examples/azuread-accesstoken/go.mod
+++ b/examples/azuread-accesstoken/go.mod
@@ -1,8 +1,8 @@
-module github.com/microsoft/go-mssqldb/examples/azure-ad-accesstoken
+module github.com/denisenkom/go-mssqldb/examples/azure-ad-accesstoken
 
 go 1.13
 
 require (
 	github.com/Azure/go-autorest/autorest/adal v0.8.1
-	github.com/microsoft/go-mssqldb v0.12.0
+	github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73
 )
diff --git a/examples/azuread-accesstoken/go.sum b/examples/azuread-accesstoken/go.sum
index 432407e..17148ff 100644
--- a/examples/azuread-accesstoken/go.sum
+++ b/examples/azuread-accesstoken/go.sum
@@ -14,8 +14,8 @@ github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN
 github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
 github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=
 github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
-github.com/microsoft/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73 h1:OGNva6WhsKst5OZf7eZOklDztV3hwtTHovdrLHV+MsA=
-github.com/microsoft/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
+github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73 h1:OGNva6WhsKst5OZf7eZOklDztV3hwtTHovdrLHV+MsA=
+github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
diff --git a/examples/azuread-accesstoken/managed_identity.go b/examples/azuread-accesstoken/managed_identity.go
index 6ff3617..0adf99c 100644
--- a/examples/azuread-accesstoken/managed_identity.go
+++ b/examples/azuread-accesstoken/managed_identity.go
@@ -7,7 +7,7 @@ import (
 	"log"
 
 	"github.com/Azure/go-autorest/autorest/adal"
-	mssql "github.com/microsoft/go-mssqldb"
+	mssql "github.com/denisenkom/go-mssqldb"
 )
 
 var (
diff --git a/examples/azuread-service-principal-authtoken/service_principal_authtoken.go b/examples/azuread-service-principal-authtoken/service_principal_authtoken.go
index 5e57119..e2d8bc6 100644
--- a/examples/azuread-service-principal-authtoken/service_principal_authtoken.go
+++ b/examples/azuread-service-principal-authtoken/service_principal_authtoken.go
@@ -1,13 +1,13 @@
 package main
 
 import (
-	"context"
 	"database/sql"
 	"flag"
 	"fmt"
 	"log"
 
-	mssql "github.com/microsoft/go-mssqldb"
+	_ "github.com/denisenkom/go-mssqldb"
+	"github.com/denisenkom/go-mssqldb/azuread"
 )
 
 var (
@@ -32,14 +32,7 @@ func main() {
 	if *debug {
 		fmt.Printf(" connString:%s\n", connString)
 	}
-
-	tokenProviderWithCtx := func(ctx context.Context) (string, error) {
-		return "access_token", nil
-	}
-
-	connector, err := mssql.NewConnectorWithAccessTokenProvider(connString, tokenProviderWithCtx)
-	conn := sql.OpenDB(connector)
-
+	conn, err := sql.Open(azuread.DriverName, connString)
 	if err != nil {
 		log.Fatal("Open connection failed:", err.Error())
 	}
diff --git a/examples/azuread-service-principal/service_principal.go b/examples/azuread-service-principal/service_principal.go
deleted file mode 100644
index 8326450..0000000
--- a/examples/azuread-service-principal/service_principal.go
+++ /dev/null
@@ -1,63 +0,0 @@
-//go:build go1.18
-// +build go1.18
-
-package main
-
-import (
-	"database/sql"
-	"flag"
-	"fmt"
-	"log"
-
-	"github.com/microsoft/go-mssqldb/azuread"
-)
-
-var (
-	debug         = flag.Bool("debug", true, "Enable debugging")
-	password      = flag.String("password", "", "The client secret for the app/client ID")
-	port     *int = flag.Int("port", 1433, "The database port")
-	server        = flag.String("server", "", "The database server")
-	user          = flag.String("user", "", "The app ID of the service principal. "+
-		"Format: <app_id>@<tenant_id>. tenant_id is optional if the app and database are in the same tenant.")
-	database = flag.String("database", "", "The database name")
-)
-
-func main() {
-	flag.Parse()
-
-	if *debug {
-		fmt.Printf(" password:%s\n", *password)
-		fmt.Printf(" port:%d\n", *port)
-		fmt.Printf(" server:%s\n", *server)
-		fmt.Printf(" user:%s\n", *user)
-		fmt.Printf(" database:%s\n", *database)
-	}
-
-	connString := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d;database=%s;fedauth=ActiveDirectoryServicePrincipal;", *server, *user, *password, *port, *database)
-	if *debug {
-		fmt.Printf(" connString:%s\n", connString)
-	}
-	conn, err := sql.Open(azuread.DriverName, connString)
-	if err != nil {
-		log.Fatal("Open connection failed:", err.Error())
-	}
-	defer conn.Close()
-
-	stmt, err := conn.Prepare("select 1, 'abc'")
-	if err != nil {
-		log.Fatal("Prepare failed:", err.Error())
-	}
-	defer stmt.Close()
-
-	row := stmt.QueryRow()
-	var somenumber int64
-	var somechars string
-	err = row.Scan(&somenumber, &somechars)
-	if err != nil {
-		log.Fatal("Scan failed:", err.Error())
-	}
-	fmt.Printf("somenumber:%d\n", somenumber)
-	fmt.Printf("somechars:%s\n", somechars)
-
-	fmt.Printf("bye\n")
-}
diff --git a/examples/bulk/bulk.go b/examples/bulk/bulk.go
index bcd6e99..8ce1238 100644
--- a/examples/bulk/bulk.go
+++ b/examples/bulk/bulk.go
@@ -6,7 +6,7 @@ import (
 	"fmt"
 	"log"
 
-	mssql "github.com/microsoft/go-mssqldb"
+	"github.com/denisenkom/go-mssqldb"
 )
 
 var (
diff --git a/examples/routine/routine.go b/examples/routine/routine.go
index 42f6513..3c9cf74 100644
--- a/examples/routine/routine.go
+++ b/examples/routine/routine.go
@@ -8,7 +8,7 @@ import (
 	"strconv"
 	"sync"
 
-	_ "github.com/microsoft/go-mssqldb"
+	_ "github.com/denisenkom/go-mssqldb"
 )
 
 var (
diff --git a/examples/simple/simple.go b/examples/simple/simple.go
index 7cb5cfc..67f88aa 100644
--- a/examples/simple/simple.go
+++ b/examples/simple/simple.go
@@ -6,7 +6,7 @@ import (
 	"fmt"
 	"log"
 
-	_ "github.com/microsoft/go-mssqldb"
+	_ "github.com/denisenkom/go-mssqldb"
 )
 
 var (
diff --git a/examples/tsql/tsql.go b/examples/tsql/tsql.go
index 69dc8d4..f90cf46 100644
--- a/examples/tsql/tsql.go
+++ b/examples/tsql/tsql.go
@@ -9,7 +9,7 @@ import (
 	"os"
 	"time"
 
-	_ "github.com/microsoft/go-mssqldb"
+	_ "github.com/denisenkom/go-mssqldb"
 )
 
 func main() {
diff --git a/examples/tvp/tvp.go b/examples/tvp/tvp.go
index 061b7f3..a07bb65 100644
--- a/examples/tvp/tvp.go
+++ b/examples/tvp/tvp.go
@@ -4,9 +4,8 @@ import (
 	"database/sql"
 	"flag"
 	"fmt"
+	"github.com/denisenkom/go-mssqldb"
 	"log"
-
-	mssql "github.com/microsoft/go-mssqldb"
 )
 
 var (
diff --git a/fedauth.go b/fedauth.go
index 27ff3fc..3f4aa96 100644
--- a/fedauth.go
+++ b/fedauth.go
@@ -4,7 +4,7 @@ import (
 	"context"
 	"errors"
 
-	"github.com/microsoft/go-mssqldb/msdsn"
+	"github.com/denisenkom/go-mssqldb/msdsn"
 )
 
 // Federated authentication library affects the login data structure and message sequence.
@@ -34,6 +34,9 @@ const (
 
 	// FedAuthADALWorkflowMSI uses the managed identity service to obtain a token
 	FedAuthADALWorkflowMSI = 0x03
+
+	// FedAuthADALWorkflowNone does not need to obtain token
+	FedAuthADALWorkflowNone = 0x04
 )
 
 // newSecurityTokenConnector creates a new connector from a Config and a token provider.
diff --git a/go.mod b/go.mod
index fd812da..8f3907d 100644
--- a/go.mod
+++ b/go.mod
@@ -1,18 +1,11 @@
-module github.com/microsoft/go-mssqldb
+module github.com/denisenkom/go-mssqldb
 
 go 1.13
 
 require (
-	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.2
-	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0
-	github.com/dnaeon/go-vcr v1.2.0 // indirect
-	github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
+	github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0
+	github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0
 	github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe
 	github.com/golang-sql/sqlexp v0.1.0
-	github.com/google/uuid v1.3.0 // indirect
-	github.com/jcmturner/gokrb5/v8 v8.4.2
-	github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
-	golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88
-	golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 // indirect
-	gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
+	golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
 )
diff --git a/go.sum b/go.sum
index b00c2e2..3e3a86c 100644
--- a/go.sum
+++ b/go.sum
@@ -1,100 +1,46 @@
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.2 h1:lneMk5qtUMulXa/eVxjVd+/bDYMEDIqYpLzLa2/EsNI=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.1.2/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
-github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE=
-github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0 h1:lhSJz9RMbJcTgxifR1hUNJnn6CNYtbgEDtQV22/9RBA=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0 h1:OYa9vmRX2XC5GXRAzeggG12sF/z5D9Ahtdm9EJ00WN4=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
+github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0 h1:v9p9TfTbf7AwNb5NYQt7hI41IfPoLFiFkLtb+bmGjT0=
+github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
-github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
 github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
-github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
-github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
-github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
-github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
-github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
 github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
 github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
-github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
-github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
-github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
-github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
-github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
-github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
-github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
-github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
-github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
-github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8=
-github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
-github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
-github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
-github.com/jcmturner/gokrb5/v8 v8.4.2 h1:6ZIM6b/JJN0X8UM43ZOM6Z4SJzla+a/u7scXFJzodkA=
-github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
-github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
-github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
-github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
-github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
 github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
-github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
-github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
-github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
-github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
+github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=
+github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw=
-golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
-golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 h1:BXxu8t6QN0G1uff4bzZzSkpsax8+ALqTGUtz08QrV00=
-golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
-gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
-gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
diff --git a/integratedauth/auth.go b/integratedauth/auth.go
deleted file mode 100644
index 0d68da7..0000000
--- a/integratedauth/auth.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package integratedauth
-
-import (
-	"errors"
-	"fmt"
-
-	"github.com/microsoft/go-mssqldb/msdsn"
-)
-
-var (
-	providers           map[string]Provider
-	DefaultProviderName string
-
-	ErrProviderCannotBeNil         = errors.New("provider cannot be nil")
-	ErrProviderNameMustBePopulated = errors.New("provider name must be populated")
-)
-
-func init() {
-	providers = make(map[string]Provider)
-}
-
-// GetIntegratedAuthenticator calls the authProvider specified in the 'authenticator' connection string parameter, if supplied.
-// Otherwise fails back to the DefaultProviderName implementation for the platform.
-func GetIntegratedAuthenticator(config msdsn.Config) (IntegratedAuthenticator, error) {
-	authenticatorName, ok := config.Parameters["authenticator"]
-	if !ok {
-		provider, err := getProvider(DefaultProviderName)
-		if err != nil {
-			return nil, err
-		}
-
-		p, err := provider.GetIntegratedAuthenticator(config)
-		// we ignore the error in this case to force a fallback to sqlserver authentication.
-		// this preserves the original behaviour
-		if err != nil {
-			return nil, nil
-		}
-
-		return p, nil
-	}
-
-	provider, err := getProvider(authenticatorName)
-	if err != nil {
-		return nil, err
-	}
-
-	return provider.GetIntegratedAuthenticator(config)
-}
-
-func getProvider(name string) (Provider, error) {
-	provider, ok := providers[name]
-
-	if !ok {
-		return nil, fmt.Errorf("provider %v not found", name)
-	}
-
-	return provider, nil
-}
-
-// SetIntegratedAuthenticationProvider stores a named authentication provider. It should be called before any connections are created.
-func SetIntegratedAuthenticationProvider(providerName string, p Provider) error {
-	if p == nil {
-		return ErrProviderCannotBeNil
-	}
-
-	if providerName == "" {
-		return ErrProviderNameMustBePopulated
-	}
-
-	providers[providerName] = p
-
-	return nil
-}
diff --git a/integratedauth/integratedauthenticator.go b/integratedauth/integratedauthenticator.go
deleted file mode 100644
index ce8240d..0000000
--- a/integratedauth/integratedauthenticator.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package integratedauth
-
-import (
-	"github.com/microsoft/go-mssqldb/msdsn"
-)
-
-// Provider returns an SSPI compatible authentication provider
-type Provider interface {
-	// GetIntegratedAuthenticator is responsible for returning an instance of the required IntegratedAuthenticator interface
-	GetIntegratedAuthenticator(config msdsn.Config) (IntegratedAuthenticator, error)
-}
-
-// IntegratedAuthenticator is the interface for SSPI Login Authentication providers
-type IntegratedAuthenticator interface {
-	InitialBytes() ([]byte, error)
-	NextBytes([]byte) ([]byte, error)
-	Free()
-}
-
-// ProviderFunc is an adapter to convert a GetIntegratedAuthenticator func into a Provider
-type ProviderFunc func(config msdsn.Config) (IntegratedAuthenticator, error)
-
-func (f ProviderFunc) GetIntegratedAuthenticator(config msdsn.Config) (IntegratedAuthenticator, error) {
-	return f(config)
-}
diff --git a/integratedauth/krb5/krb5.go b/integratedauth/krb5/krb5.go
deleted file mode 100644
index 6d96871..0000000
--- a/integratedauth/krb5/krb5.go
+++ /dev/null
@@ -1,268 +0,0 @@
-//go:build !windows && go1.13
-// +build !windows,go1.13
-
-package krb5
-
-import (
-	"errors"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"strconv"
-	"strings"
-
-	"github.com/jcmturner/gokrb5/v8/client"
-	"github.com/jcmturner/gokrb5/v8/config"
-	"github.com/jcmturner/gokrb5/v8/credentials"
-	"github.com/jcmturner/gokrb5/v8/keytab"
-	"github.com/jcmturner/gokrb5/v8/spnego"
-	"github.com/microsoft/go-mssqldb/integratedauth"
-	"github.com/microsoft/go-mssqldb/msdsn"
-)
-
-var (
-	SetKrbConfig = setupKerbConfig
-	SetKrbKeytab = setupKerbKeytab
-	SetKrbCache  = setupKerbCache
-)
-
-// Kerberos Client State
-type krb5ClientState int
-
-type krb5Auth struct {
-	username   string
-	password   string
-	realm      string
-	serverSPN  string
-	port       uint64
-	krb5Config *config.Config
-	krbKeytab  *keytab.Keytab
-	krbCache   *credentials.CCache
-	krb5Client *client.Client
-	state      krb5ClientState
-}
-
-type Kerberos struct {
-	// Kerberos configuration details
-	Config *config.Config
-
-	// Credential cache
-	Cache *credentials.CCache
-
-	// A Kerberos realm is the domain over which a Kerberos authentication server has the authority
-	// to authenticate a user, host or service.
-	Realm string
-
-	// Kerberos keytab that stores long-term keys for one or more principals
-	Keytab *keytab.Keytab
-}
-
-const (
-	// Initiator states
-	initiatorStart        krb5ClientState = iota
-	initiatorWaitForMutal                 = iota + 2
-	initiatorReady
-)
-
-var (
-	_                integratedauth.IntegratedAuthenticator = (*krb5Auth)(nil)
-	AuthProviderFunc integratedauth.Provider                = integratedauth.ProviderFunc(getAuth)
-)
-
-func init() {
-	err := integratedauth.SetIntegratedAuthenticationProvider("krb5", AuthProviderFunc)
-	if err != nil {
-		panic(err)
-	}
-}
-
-func getAuth(config msdsn.Config) (integratedauth.IntegratedAuthenticator, error) {
-	var port uint64
-	var realm, serviceStr string
-	var err error
-
-	krb, err := readKrb5Config(config)
-	if err != nil {
-		return &krb5Auth{}, err
-	}
-	params1 := strings.Split(config.ServerSPN, ":")
-	if len(params1) != 2 {
-		return nil, errors.New("invalid ServerSPN")
-	}
-
-	params2 := strings.Split(params1[1], "@")
-	switch len(params2) {
-	case 1:
-		port, err = strconv.ParseUint(params1[1], 10, 16)
-		if err != nil {
-			return nil, err
-		}
-	case 2:
-		port, err = strconv.ParseUint(params2[0], 10, 16)
-		if err != nil {
-			return nil, err
-		}
-	default:
-		return nil, errors.New("invalid ServerSPN")
-	}
-
-	params3 := strings.Split(config.ServerSPN, "@")
-	switch len(params3) {
-	case 1:
-		serviceStr = params3[0]
-		params3 = strings.Split(params1[0], "/")
-		params3 = strings.Split(params3[1], ".")
-		realm = params3[1] + "." + params3[2]
-	case 2:
-		realm = params3[1]
-		serviceStr = params3[0]
-	default:
-		return nil, errors.New("invalid ServerSPN")
-	}
-
-	return &krb5Auth{
-		username:   config.User,
-		password:   config.Password,
-		serverSPN:  serviceStr,
-		port:       port,
-		realm:      realm,
-		krb5Config: krb.Config,
-		krbKeytab:  krb.Keytab,
-		krbCache:   krb.Cache,
-	}, nil
-}
-
-func (auth *krb5Auth) InitialBytes() ([]byte, error) {
-	var cl *client.Client
-	var err error
-	// Init keytab from conf
-	if auth.username != "" && auth.password != "" {
-		cl = client.NewWithPassword(auth.username, auth.realm, auth.password, auth.krb5Config)
-	} else if auth.krbKeytab != nil {
-		// Init krb5 client and login
-		cl = client.NewWithKeytab(auth.username, auth.realm, auth.krbKeytab, auth.krb5Config, client.DisablePAFXFAST(true))
-	} else {
-		cl, err = client.NewFromCCache(auth.krbCache, auth.krb5Config)
-		if err != nil {
-			return []byte{}, err
-		}
-	}
-	auth.krb5Client = cl
-	auth.state = initiatorStart
-	tkt, sessionKey, err := cl.GetServiceTicket(auth.serverSPN)
-	if err != nil {
-		return []byte{}, err
-	}
-
-	negTok, err := spnego.NewNegTokenInitKRB5(auth.krb5Client, tkt, sessionKey)
-	if err != nil {
-		return []byte{}, err
-	}
-
-	outToken, err := negTok.Marshal()
-	if err != nil {
-		return []byte{}, err
-	}
-	auth.state = initiatorWaitForMutal
-	return outToken, nil
-}
-
-func (auth *krb5Auth) Free() {
-	auth.krb5Client.Destroy()
-}
-
-func (auth *krb5Auth) NextBytes(token []byte) ([]byte, error) {
-	var spnegoToken spnego.SPNEGOToken
-	if err := spnegoToken.Unmarshal(token); err != nil {
-		err := fmt.Errorf("unmarshal APRep token failed: %w", err)
-		return []byte{}, err
-	}
-	auth.state = initiatorReady
-	return []byte{}, nil
-}
-
-func readKrb5Config(config msdsn.Config) (Kerberos, error) {
-	krb := Kerberos{}
-	var err error
-
-	krbConfig, ok := config.Parameters["krb5conffile"]
-	if !ok {
-		return krb, fmt.Errorf("krb5 config file is required")
-	}
-
-	krb.Config, err = SetKrbConfig(krbConfig)
-	if err != nil {
-		return krb, err
-	}
-
-	missingParam := validateKerbConfig(config.Parameters)
-	if missingParam != "" {
-		return krb, fmt.Errorf("missing parameter:%s", missingParam)
-	}
-
-	if realm, ok := config.Parameters["realm"]; ok {
-		krb.Realm = realm
-	}
-
-	if krbCache, ok := config.Parameters["krbcache"]; ok {
-		krb.Cache, err = SetKrbCache(krbCache)
-		if err != nil {
-			return krb, err
-		}
-	}
-
-	if keytabfile, ok := config.Parameters["keytabfile"]; ok {
-		krb.Keytab, err = SetKrbKeytab(keytabfile)
-		if err != nil {
-			return krb, err
-		}
-	}
-
-	return krb, nil
-}
-
-func validateKerbConfig(c map[string]string) (missingParam string) {
-	if c["keytabfile"] != "" {
-		if c["realm"] == "" {
-			missingParam = "realm"
-			return
-		}
-	}
-	if c["krbcache"] == "" && c["keytabfile"] == "" {
-		missingParam = "atleast krbcache or keytab is required"
-		return
-	}
-	return
-}
-
-func setupKerbConfig(krb5configPath string) (*config.Config, error) {
-	krb5CnfFile, err := os.Open(krb5configPath)
-	if err != nil {
-		return nil, err
-	}
-	c, err := config.NewFromReader(krb5CnfFile)
-	if err != nil {
-		return nil, err
-	}
-	return c, nil
-}
-
-func setupKerbCache(kerbCCahePath string) (*credentials.CCache, error) {
-	cache, err := credentials.LoadCCache(kerbCCahePath)
-	if err != nil {
-		return nil, err
-	}
-	return cache, nil
-}
-
-func setupKerbKeytab(keytabFilePath string) (*keytab.Keytab, error) {
-	var kt = &keytab.Keytab{}
-	keytabConf, err := ioutil.ReadFile(keytabFilePath)
-	if err != nil {
-		return nil, err
-	}
-	if err = kt.Unmarshal([]byte(keytabConf)); err != nil {
-		return nil, err
-	}
-	return kt, nil
-}
diff --git a/integratedauth/ntlm/provider.go b/integratedauth/ntlm/provider.go
deleted file mode 100644
index b0c780b..0000000
--- a/integratedauth/ntlm/provider.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package ntlm
-
-import (
-	"github.com/microsoft/go-mssqldb/integratedauth"
-)
-
-// AuthProvider handles NTLM SSPI Windows Authentication
-var AuthProvider integratedauth.Provider = integratedauth.ProviderFunc(getAuth)
-
-func init() {
-	err := integratedauth.SetIntegratedAuthenticationProvider("ntlm", AuthProvider)
-	if err != nil {
-		panic(err)
-	}
-}
diff --git a/integratedauth/winsspi/provider.go b/integratedauth/winsspi/provider.go
deleted file mode 100644
index 05da93f..0000000
--- a/integratedauth/winsspi/provider.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// +build windows
-
-package winsspi
-
-import "github.com/microsoft/go-mssqldb/integratedauth"
-
-// AuthProvider handles SSPI Windows Authentication via secur32.dll functions
-var AuthProvider integratedauth.Provider = integratedauth.ProviderFunc(getAuth)
-
-func init() {
-	err := integratedauth.SetIntegratedAuthenticationProvider("winsspi", AuthProvider)
-	if err != nil {
-		panic(err)
-	}
-}
\ No newline at end of file
diff --git a/log.go b/log.go
index 8ccb403..8d99bd5 100644
--- a/log.go
+++ b/log.go
@@ -3,7 +3,7 @@ package mssql
 import (
 	"context"
 
-	"github.com/microsoft/go-mssqldb/msdsn"
+	"github.com/denisenkom/go-mssqldb/msdsn"
 )
 
 const (
diff --git a/msdsn/conn_str.go b/msdsn/conn_str.go
index c25f090..40bedb0 100644
--- a/msdsn/conn_str.go
+++ b/msdsn/conn_str.go
@@ -69,31 +69,23 @@ type Config struct {
 
 	// Do not use the following.
 
-	DialTimeout time.Duration // DialTimeout defaults to 15s per protocol. Set negative to disable.
+	DialTimeout time.Duration // DialTimeout defaults to 15s. Set negative to disable.
 	ConnTimeout time.Duration // Use context for timeouts.
 	KeepAlive   time.Duration // Leave at default.
 	PacketSize  uint16
-
-	Parameters map[string]string
-	// Protocols is an ordered list of protocols to dial
-	Protocols []string
-	// ProtocolParameters are written by non-tcp ProtocolParser implementations
-	ProtocolParameters map[string]interface{}
 }
 
-func SetupTLS(certificate string, insecureSkipVerify bool, hostInCertificate string, minTLSVersion string) (*tls.Config, error) {
+func SetupTLS(certificate string, insecureSkipVerify bool, hostInCertificate string) (*tls.Config, error) {
 	config := tls.Config{
 		ServerName:         hostInCertificate,
 		InsecureSkipVerify: insecureSkipVerify,
 
-		// fix for https://github.com/microsoft/go-mssqldb/issues/166
+		// fix for https://github.com/denisenkom/go-mssqldb/issues/166
 		// Go implementation of TLS payload size heuristic algorithm splits single TDS package to multiple TCP segments,
 		// while SQL Server seems to expect one TCP segment per encrypted TDS package.
 		// Setting DynamicRecordSizingDisabled to true disables that algorithm and uses 16384 bytes per TLS package
 		DynamicRecordSizingDisabled: true,
-		MinVersion:                  TLSVersionFromString(minTLSVersion),
 	}
-
 	if len(certificate) == 0 {
 		return &config, nil
 	}
@@ -115,39 +107,43 @@ func SetupTLS(certificate string, insecureSkipVerify bool, hostInCertificate str
 
 var skipSetup = errors.New("skip setting up TLS")
 
-func Parse(dsn string) (Config, error) {
-	p := Config{
-		ProtocolParameters: map[string]interface{}{},
-		Protocols:          []string{},
-	}
+func Parse(dsn string) (Config, map[string]string, error) {
+	p := Config{}
 
 	var params map[string]string
-	var err error
 	if strings.HasPrefix(dsn, "odbc:") {
-		params, err = splitConnectionStringOdbc(dsn[len("odbc:"):])
+		parameters, err := splitConnectionStringOdbc(dsn[len("odbc:"):])
 		if err != nil {
-			return p, err
+			return p, params, err
 		}
+		params = parameters
 	} else if strings.HasPrefix(dsn, "sqlserver://") {
-		params, err = splitConnectionStringURL(dsn)
+		parameters, err := splitConnectionStringURL(dsn)
 		if err != nil {
-			return p, err
+			return p, params, err
 		}
+		params = parameters
 	} else {
 		params = splitConnectionString(dsn)
 	}
 
-	p.Parameters = params
-
 	strlog, ok := params["log"]
 	if ok {
 		flags, err := strconv.ParseUint(strlog, 10, 64)
 		if err != nil {
-			return p, fmt.Errorf("invalid log parameter '%s': %s", strlog, err.Error())
+			return p, params, fmt.Errorf("invalid log parameter '%s': %s", strlog, err.Error())
 		}
 		p.LogFlags = Log(flags)
 	}
-
+	server := params["server"]
+	parts := strings.SplitN(server, `\`, 2)
+	p.Host = parts[0]
+	if p.Host == "." || strings.ToUpper(p.Host) == "(LOCAL)" || p.Host == "" {
+		p.Host = "localhost"
+	}
+	if len(parts) > 1 {
+		p.Instance = parts[1]
+	}
 	p.Database = params["database"]
 	p.User = params["user id"]
 	p.Password = params["password"]
@@ -159,7 +155,7 @@ func Parse(dsn string) (Config, error) {
 		p.Port, err = strconv.ParseUint(strport, 10, 16)
 		if err != nil {
 			f := "invalid tcp port '%v': %v"
-			return p, fmt.Errorf(f, strport, err.Error())
+			return p, params, fmt.Errorf(f, strport, err.Error())
 		}
 	}
 
@@ -170,7 +166,7 @@ func Parse(dsn string) (Config, error) {
 		psize, err := strconv.ParseUint(strpsize, 0, 16)
 		if err != nil {
 			f := "invalid packet size '%v': %v"
-			return p, fmt.Errorf(f, strpsize, err.Error())
+			return p, params, fmt.Errorf(f, strpsize, err.Error())
 		}
 
 		// Ensure packet size falls within the TDS protocol range of 512 to 32767 bytes
@@ -193,22 +189,17 @@ func Parse(dsn string) (Config, error) {
 		timeout, err := strconv.ParseUint(strconntimeout, 10, 64)
 		if err != nil {
 			f := "invalid connection timeout '%v': %v"
-			return p, fmt.Errorf(f, strconntimeout, err.Error())
+			return p, params, fmt.Errorf(f, strconntimeout, err.Error())
 		}
 		p.ConnTimeout = time.Duration(timeout) * time.Second
 	}
-	f := len(p.Protocols)
-	if f == 0 {
-		f = 1
-	}
-	p.DialTimeout = time.Duration(15*f) * time.Second
+	p.DialTimeout = 15 * time.Second
 	if strdialtimeout, ok := params["dial timeout"]; ok {
 		timeout, err := strconv.ParseUint(strdialtimeout, 10, 64)
 		if err != nil {
 			f := "invalid dial timeout '%v': %v"
-			return p, fmt.Errorf(f, strdialtimeout, err.Error())
+			return p, params, fmt.Errorf(f, strdialtimeout, err.Error())
 		}
-
 		p.DialTimeout = time.Duration(timeout) * time.Second
 	}
 
@@ -219,7 +210,7 @@ func Parse(dsn string) (Config, error) {
 		timeout, err := strconv.ParseUint(keepAlive, 10, 64)
 		if err != nil {
 			f := "invalid keepAlive value '%s': %s"
-			return p, fmt.Errorf(f, keepAlive, err.Error())
+			return p, params, fmt.Errorf(f, keepAlive, err.Error())
 		}
 		p.KeepAlive = time.Duration(timeout) * time.Second
 	}
@@ -237,7 +228,7 @@ func Parse(dsn string) (Config, error) {
 			e, err := strconv.ParseBool(encrypt)
 			if err != nil {
 				f := "invalid encrypt '%s': %s"
-				return p, fmt.Errorf(f, encrypt, err.Error())
+				return p, params, fmt.Errorf(f, encrypt, err.Error())
 			}
 			if e {
 				p.Encryption = EncryptionRequired
@@ -252,7 +243,7 @@ func Parse(dsn string) (Config, error) {
 		trustServerCert, err = strconv.ParseBool(trust)
 		if err != nil {
 			f := "invalid trust server certificate '%s': %s"
-			return p, fmt.Errorf(f, trust, err.Error())
+			return p, params, fmt.Errorf(f, trust, err.Error())
 		}
 	}
 	certificate = params["certificate"]
@@ -265,11 +256,10 @@ func Parse(dsn string) (Config, error) {
 	}
 
 	if p.Encryption != EncryptionDisabled {
-		tlsMin := params["tlsmin"]
 		var err error
-		p.TLSConfig, err = SetupTLS(certificate, trustServerCert, hostInCertificate, tlsMin)
+		p.TLSConfig, err = SetupTLS(certificate, trustServerCert, hostInCertificate)
 		if err != nil {
-			return p, fmt.Errorf("failed to setup TLS: %w", err)
+			return p, params, fmt.Errorf("failed to setup TLS: %w", err)
 		}
 	}
 
@@ -277,8 +267,7 @@ func Parse(dsn string) (Config, error) {
 	if ok {
 		p.ServerSPN = serverSPN
 	} else {
-		// allow connections to sql server instances
-		p.ServerSPN = generateSpn(p.Host, instanceOrPort(p.Instance, p.Port))
+		p.ServerSPN = generateSpn(p.Host, p.Port)
 	}
 
 	workstation, ok := params["workstation id"]
@@ -301,7 +290,7 @@ func Parse(dsn string) (Config, error) {
 	if ok {
 		if appintent == "ReadOnly" {
 			if p.Database == "" {
-				return p, fmt.Errorf("database must be specified when ApplicationIntent is ReadOnly")
+				return p, params, fmt.Errorf("database must be specified when ApplicationIntent is ReadOnly")
 			}
 			p.ReadOnlyIntent = true
 		}
@@ -318,7 +307,7 @@ func Parse(dsn string) (Config, error) {
 		p.FailOverPort, err = strconv.ParseUint(failOverPort, 0, 16)
 		if err != nil {
 			f := "invalid failover port '%v': %v"
-			return p, fmt.Errorf(f, failOverPort, err.Error())
+			return p, params, fmt.Errorf(f, failOverPort, err.Error())
 		}
 	}
 
@@ -328,35 +317,13 @@ func Parse(dsn string) (Config, error) {
 		p.DisableRetry, err = strconv.ParseBool(disableRetry)
 		if err != nil {
 			f := "invalid disableRetry '%s': %s"
-			return p, fmt.Errorf(f, disableRetry, err.Error())
+			return p, params, fmt.Errorf(f, disableRetry, err.Error())
 		}
 	} else {
 		p.DisableRetry = disableRetryDefault
 	}
 
-	server := params["server"]
-	protocol, ok := params["protocol"]
-
-	for _, parser := range ProtocolParsers {
-		if !ok || parser.Protocol() == protocol {
-			err = parser.ParseServer(server, &p)
-			if err != nil {
-				// if the caller only wants this protocol , fail right away
-				if ok {
-					return p, err
-				}
-			} else {
-				// Only enable a protocol if it can handle the server name
-				p.Protocols = append(p.Protocols, parser.Protocol())
-			}
-
-		}
-	}
-	if ok && len(p.Protocols) == 0 {
-		return p, fmt.Errorf("No protocol handler is available for protocol: '%s'", protocol)
-	}
-
-	return p, nil
+	return p, params, nil
 }
 
 // convert connectionParams to url style connection string
@@ -374,10 +341,6 @@ func (p Config) URL() *url.URL {
 		host = fmt.Sprintf("%s:%d", p.Host, p.Port)
 	}
 	q.Add("disableRetry", fmt.Sprintf("%t", p.DisableRetry))
-	protocol, ok := p.Parameters["protocol"]
-	if ok {
-		q.Add("protocol", protocol)
-	}
 	res := url.URL{
 		Scheme: "sqlserver",
 		Host:   host,
@@ -386,11 +349,9 @@ func (p Config) URL() *url.URL {
 	if p.Instance != "" {
 		res.Path = p.Instance
 	}
-	q.Add("dial timeout", strconv.FormatFloat(float64(p.DialTimeout.Seconds()), 'f', 0, 64))
 	if len(q) > 0 {
 		res.RawQuery = q.Encode()
 	}
-
 	return &res
 }
 
@@ -426,14 +387,9 @@ func splitConnectionString(dsn string) (res map[string]string) {
 			name = synonym
 		}
 		// "server" in ADO can include a protocol and a port.
+		// We only support tcp protocol
 		if name == "server" {
-			for _, parser := range ProtocolParsers {
-				prot := parser.Protocol() + ":"
-				if strings.HasPrefix(value, prot) {
-					res["protocol"] = parser.Protocol()
-				}
-				value = strings.TrimPrefix(value, prot)
-			}
+			value = strings.TrimPrefix(value, "tcp:")
 			serverParts := strings.Split(value, ",")
 			if len(serverParts) == 2 && len(serverParts[1]) > 0 {
 				value = serverParts[0]
@@ -649,56 +605,6 @@ func normalizeOdbcKey(s string) string {
 	return strings.ToLower(strings.TrimRightFunc(s, unicode.IsSpace))
 }
 
-func instanceOrPort(instance string, port uint64) string {
-	if len(instance) > 0 {
-		return instance
-	}
-
-	port = resolveServerPort(port)
-
-	return strconv.FormatInt(int64(port), 10)
-}
-
-const defaultServerPort = 1433
-
-func resolveServerPort(port uint64) uint64 {
-	if port == 0 {
-		return defaultServerPort
-	}
-
-	return port
-}
-
-func generateSpn(host string, port string) string {
-	return fmt.Sprintf("MSSQLSvc/%s:%s", host, port)
-}
-
-// ProtocolParser can populate Config with parameters to dial using its protocol
-type ProtocolParser interface {
-	ParseServer(server string, p *Config) error
-	Protocol() string
-}
-
-// ProtocolParsers is an ordered list of protocols that can be dialed. Each parser must have a corresponding Dialer in mssql.ProtocolDialers
-var ProtocolParsers []ProtocolParser = []ProtocolParser{
-	tcpParser{},
-}
-
-type tcpParser struct{}
-
-func (t tcpParser) ParseServer(server string, p *Config) error {
-	// a server name can have different forms
-	parts := strings.SplitN(server, `\`, 2)
-	p.Host = parts[0]
-	if p.Host == "." || strings.ToUpper(p.Host) == "(LOCAL)" || p.Host == "" {
-		p.Host = "localhost"
-	}
-	if len(parts) > 1 {
-		p.Instance = parts[1]
-	}
-	return nil
-}
-
-func (t tcpParser) Protocol() string {
-	return "tcp"
+func generateSpn(host string, port uint64) string {
+	return fmt.Sprintf("MSSQLSvc/%s:%d", host, port)
 }
diff --git a/msdsn/conn_str_go112.go b/msdsn/conn_str_go112.go
deleted file mode 100644
index 3ae4dce..0000000
--- a/msdsn/conn_str_go112.go
+++ /dev/null
@@ -1,22 +0,0 @@
-//go:build go1.12
-// +build go1.12
-
-package msdsn
-
-import "crypto/tls"
-
-func TLSVersionFromString(minTLSVersion string) uint16 {
-	switch minTLSVersion {
-	case "1.0":
-		return tls.VersionTLS10
-	case "1.1":
-		return tls.VersionTLS11
-	case "1.2":
-		return tls.VersionTLS12
-	case "1.3":
-		return tls.VersionTLS13
-	default:
-		// use the tls package default
-	}
-	return 0
-}
diff --git a/msdsn/conn_str_go112pre.go b/msdsn/conn_str_go112pre.go
deleted file mode 100644
index 7b47b6b..0000000
--- a/msdsn/conn_str_go112pre.go
+++ /dev/null
@@ -1,20 +0,0 @@
-//go:build !go1.12
-// +build !go1.12
-
-package msdsn
-
-import "crypto/tls"
-
-func TLSVersionFromString(minTLSVersion string) uint16 {
-	switch minTLSVersion {
-	case "1.0":
-		return tls.VersionTLS10
-	case "1.1":
-		return tls.VersionTLS11
-	case "1.2":
-		return tls.VersionTLS12
-	default:
-		// use the tls package default
-	}
-	return 0
-}
diff --git a/msdsn/extensions.go b/msdsn/extensions.go
deleted file mode 100644
index 221b92e..0000000
--- a/msdsn/extensions.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package msdsn
-
-import (
-	"context"
-	"net"
-)
-
-type BrowserData map[string]map[string]string
-
-// ProtocolDialer makes the network connection for a protocol
-type ProtocolDialer interface {
-	// Translates data from SQL Browser to parameters in the config
-	ParseBrowserData(data BrowserData, p *Config) error
-	// DialConnection eturns a Dialer to make the connection
-	DialConnection(ctx context.Context, p Config) (conn net.Conn, err error)
-	// Returns true if information is needed from the SQL Browser service to make a connection
-	CallBrowser(p *Config) bool
-}
-
-var ProtocolDialers map[string]ProtocolDialer = map[string]ProtocolDialer{}
diff --git a/mssql.go b/mssql.go
index 28288a4..fbd44d1 100644
--- a/mssql.go
+++ b/mssql.go
@@ -9,16 +9,15 @@ import (
 	"fmt"
 	"io"
 	"math"
-	"math/bits"
 	"net"
 	"reflect"
 	"strings"
 	"time"
 	"unicode"
 
+	"github.com/denisenkom/go-mssqldb/internal/querytext"
+	"github.com/denisenkom/go-mssqldb/msdsn"
 	"github.com/golang-sql/sqlexp"
-	"github.com/microsoft/go-mssqldb/internal/querytext"
-	"github.com/microsoft/go-mssqldb/msdsn"
 )
 
 // ReturnStatus may be used to return the return value from a proc.
@@ -41,7 +40,6 @@ func init() {
 		}
 		return netDialer{&net.Dialer{KeepAlive: ka}}
 	}
-	msdsn.ProtocolDialers["tcp"] = tcpDialer{}
 }
 
 var createDialer func(p *msdsn.Config) Dialer
@@ -62,7 +60,7 @@ type Driver struct {
 
 // OpenConnector opens a new connector. Useful to dial with a context.
 func (d *Driver) OpenConnector(dsn string) (*Connector, error) {
-	params, err := msdsn.Parse(dsn)
+	params, _, err := msdsn.Parse(dsn)
 	if err != nil {
 		return nil, err
 	}
@@ -116,7 +114,7 @@ func (d *Driver) SetContextLogger(ctxLogger ContextLogger) {
 // NewConnector creates a new connector from a DSN.
 // The returned connector may be used with sql.OpenDB.
 func NewConnector(dsn string) (*Connector, error) {
-	params, err := msdsn.Parse(dsn)
+	params, _, err := msdsn.Parse(dsn)
 	if err != nil {
 		return nil, err
 	}
@@ -127,20 +125,6 @@ func NewConnector(dsn string) (*Connector, error) {
 	return c, nil
 }
 
-// NewConnectorWithAccessTokenProvider creates a new connector from a DSN using the given
-// access token provider. The returned connector may be used with sql.OpenDB.
-func NewConnectorWithAccessTokenProvider(dsn string, tokenProvider func(ctx context.Context) (string, error)) (*Connector, error) {
-	params, err := msdsn.Parse(dsn)
-	if err != nil {
-		return nil, err
-	}
-
-	return NewSecurityTokenConnector(
-		params,
-		tokenProvider,
-	)
-}
-
 // NewConnectorConfig creates a new Connector for a DSN Config struct.
 // The returned connector may be used with sql.OpenDB.
 func NewConnectorConfig(config msdsn.Config) *Connector {
@@ -388,7 +372,7 @@ func (c *Conn) processBeginResponse(ctx context.Context) (driver.Tx, error) {
 }
 
 func (d *Driver) open(ctx context.Context, dsn string) (*Conn, error) {
-	params, err := msdsn.Parse(dsn)
+	params, _, err := msdsn.Parse(dsn)
 	if err != nil {
 		return nil, err
 	}
@@ -429,7 +413,6 @@ func (d *Driver) connect(ctx context.Context, c *Connector, params msdsn.Config)
 }
 
 func (c *Conn) Close() error {
-	c.sess.buf.bufClose()
 	return c.sess.buf.transport.Close()
 }
 
@@ -923,34 +906,6 @@ func (s *Stmt) makeParam(val driver.Value) (res param, err error) {
 		return
 	}
 	switch val := val.(type) {
-	case int:
-		res.ti.TypeId = typeIntN
-		// Rather than guess if the caller intends to pass a 32bit int from a 64bit app based on the
-		// value of the int, we'll just match the runtime size of int.
-		// Apps that want a 32bit int should use int32
-		if bits.UintSize == 32 {
-			res.buffer = make([]byte, 4)
-			res.ti.Size = 4
-			binary.LittleEndian.PutUint32(res.buffer, uint32(val))
-		} else {
-			res.buffer = make([]byte, 8)
-			res.ti.Size = 8
-			binary.LittleEndian.PutUint64(res.buffer, uint64(val))
-		}
-	case int8:
-		res.ti.TypeId = typeIntN
-		res.buffer = []byte{byte(val)}
-		res.ti.Size = 1
-	case int16:
-		res.ti.TypeId = typeIntN
-		res.buffer = make([]byte, 2)
-		res.ti.Size = 2
-		binary.LittleEndian.PutUint16(res.buffer, uint16(val))
-	case int32:
-		res.ti.TypeId = typeIntN
-		res.buffer = make([]byte, 4)
-		res.ti.Size = 4
-		binary.LittleEndian.PutUint32(res.buffer, uint32(val))
 	case int64:
 		res.ti.TypeId = typeIntN
 		res.buffer = make([]byte, 8)
@@ -1119,6 +1074,7 @@ type Rowsq struct {
 	stmt        *Stmt
 	cols        []columnStruct
 	reader      *tokenProcessor
+	nextCols    []columnStruct
 	cancel      func()
 	requestDone bool
 	inResultSet bool
@@ -1146,11 +1102,8 @@ func (rc *Rowsq) Close() error {
 	}
 }
 
-// ProcessSingleResponse queues MsgNext for every columns token.
-// data/sql calls Columns during the app's call to Next.
+// data/sql calls Columns during the app's call to Next
 func (rc *Rowsq) Columns() (res []string) {
-	// r.cols is nil if the first query in a batch is a SELECT or similar query that returns a rowset.
-	// if will be non-nil for subsequent queries where NextResultSet() has populated it
 	if rc.cols == nil {
 	scan:
 		for {
@@ -1192,10 +1145,6 @@ func (rc *Rowsq) Next(dest []driver.Value) error {
 			if tok == nil {
 				return io.EOF
 			} else {
-				switch tokdata := tok.(type) {
-				case doneInProcStruct:
-					tok = (doneStruct)(tokdata)
-				}
 				switch tokdata := tok.(type) {
 				case []interface{}:
 					for i := range dest {
@@ -1223,11 +1172,9 @@ func (rc *Rowsq) Next(dest []driver.Value) error {
 					if rc.reader.outs.returnStatus != nil {
 						*rc.reader.outs.returnStatus = tokdata
 					}
-				case ServerError:
-					rc.requestDone = true
-					return tokdata
 				}
 			}
+
 		} else {
 			return rc.stmt.c.checkBadConn(rc.reader.ctx, err, false)
 		}
@@ -1240,7 +1187,7 @@ func (rc *Rowsq) HasNextResultSet() bool {
 	return !rc.requestDone
 }
 
-// Scans to the end of the current statement being processed
+// Scans to the next set of columns in the stream
 // Note that the caller may not have read all the rows in the prior set
 func (rc *Rowsq) NextResultSet() error {
 	if rc.requestDone {
@@ -1248,6 +1195,7 @@ func (rc *Rowsq) NextResultSet() error {
 	}
 scan:
 	for {
+		// we should have a columns token in the channel if we aren't at the end
 		tok, err := rc.reader.nextToken()
 		if rc.reader.sess.logFlags&logDebug != 0 {
 			rc.reader.sess.logger.Log(rc.reader.ctx, msdsn.LogDebug, fmt.Sprintf("NextResultSet() token type:%v", reflect.TypeOf(tok)))
@@ -1260,42 +1208,23 @@ scan:
 			return io.EOF
 		}
 		switch tokdata := tok.(type) {
-		case doneInProcStruct:
-			tok = (doneStruct)(tokdata)
-		}
-		// ProcessSingleResponse queues a MsgNextResult for every "done" and "server error" token
-		// The only tokens to consume after a "done" should be "done", "server error", or "columns"
-		switch tokdata := tok.(type) {
 		case []columnStruct:
-			rc.cols = tokdata
+			rc.nextCols = tokdata
 			rc.inResultSet = true
 			break scan
 		case doneStruct:
 			if tokdata.Status&doneMore == 0 {
+				rc.nextCols = nil
 				rc.requestDone = true
+				break scan
 			}
-			if tokdata.isError() {
-				e := rc.stmt.c.checkBadConn(rc.reader.ctx, tokdata.getError(), false)
-				switch e.(type) {
-				case Error:
-					// Ignore non-fatal server errors. Fatal errors are of type ServerError
-				default:
-					return e
-				}
-			}
-			rc.inResultSet = false
-			rc.cols = nil
-			break scan
-		case ReturnStatus:
-			if rc.reader.outs.returnStatus != nil {
-				*rc.reader.outs.returnStatus = tokdata
-			}
-		case ServerError:
-			rc.requestDone = true
-			return tokdata
 		}
 	}
-
+	rc.cols = rc.nextCols
+	rc.nextCols = nil
+	if rc.cols == nil {
+		return io.EOF
+	}
 	return nil
 }
 
diff --git a/mssql_go19.go b/mssql_go19.go
index 688b5c5..508b03a 100644
--- a/mssql_go19.go
+++ b/mssql_go19.go
@@ -1,4 +1,3 @@
-//go:build go1.9
 // +build go1.9
 
 package mssql
@@ -43,8 +42,6 @@ type DateTimeOffset time.Time
 
 func convertInputParameter(val interface{}) (interface{}, error) {
 	switch v := val.(type) {
-	case int, int16, int32, int64, int8:
-		return val, nil
 	case VarChar:
 		return val, nil
 	case NVarCharMax:
diff --git a/namedpipe/namedpipe.go b/namedpipe/namedpipe.go
deleted file mode 100644
index d33e8a6..0000000
--- a/namedpipe/namedpipe.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package namedpipe
-
-import (
-	"runtime"
-
-	"github.com/microsoft/go-mssqldb/msdsn"
-)
-
-type namedPipeDialer struct{}
-
-var dialer namedPipeDialer = namedPipeDialer{}
-
-func init() {
-	if runtime.GOOS == "windows" {
-		msdsn.ProtocolParsers = append(msdsn.ProtocolParsers, dialer)
-		msdsn.ProtocolDialers["np"] = dialer
-	}
-}
diff --git a/namedpipe/namedpipe_windows.go b/namedpipe/namedpipe_windows.go
deleted file mode 100644
index d69bed1..0000000
--- a/namedpipe/namedpipe_windows.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package namedpipe
-
-import (
-	"context"
-	"fmt"
-	"net"
-	"reflect"
-	"strings"
-	"time"
-
-	"github.com/microsoft/go-mssqldb/msdsn"
-	"gopkg.in/natefinch/npipe.v2"
-)
-
-type namedPipeData struct {
-	PipeName string
-}
-
-func (n namedPipeDialer) ParseServer(server string, p *msdsn.Config) error {
-	// assume a server name starting with \\ is the full named pipe path
-	if strings.HasPrefix(server, `\\`) {
-		p.ProtocolParameters[n.Protocol()] = &namedPipeData{PipeName: server}
-	} else if p.Port > 0 {
-		return fmt.Errorf("Named pipes disallowed due to port being specified")
-	} else if p.Host == "" { // if the string specifies np:host\instance, tcpParser won't have filled in p.Host
-		parts := strings.SplitN(server, `\`, 2)
-		p.Host = parts[0]
-		if p.Host == "." || strings.ToUpper(p.Host) == "(LOCAL)" {
-			p.Host = "localhost"
-		}
-		if len(parts) > 1 {
-			p.Instance = parts[1]
-		}
-	}
-	return nil
-}
-
-func (n namedPipeDialer) Protocol() string {
-	return "np"
-}
-
-func (n namedPipeDialer) ParseBrowserData(data msdsn.BrowserData, p *msdsn.Config) error {
-	// If instance is specified, but no port, check SQL Server Browser
-	// for the instance and discover its port.
-	p.Instance = strings.ToUpper(p.Instance)
-	instance := p.Instance
-	if instance == "" {
-		instance = "MSSQLSERVER"
-	}
-	pipename, ok := data[instance]["np"]
-	if !ok {
-		f := "no named pipe instance matching '%v' returned from host '%v'"
-		return fmt.Errorf(f, p.Instance, p.Host)
-	}
-	p.ProtocolParameters[n.Protocol()] = namedPipeData{PipeName: pipename}
-	return nil
-}
-
-func (n namedPipeDialer) DialConnection(ctx context.Context, p msdsn.Config) (conn net.Conn, err error) {
-	data := p.ProtocolParameters[n.Protocol()]
-	switch d := data.(type) {
-	case namedPipeData:
-		dl, ok := ctx.Deadline()
-		if ok {
-			duration := dl.Sub(time.Now())
-			return npipe.DialTimeout(d.PipeName, duration)
-		}
-		return npipe.Dial(d.PipeName)
-	}
-	return nil, fmt.Errorf("Unexpected protocol data specified for connection: %v", reflect.TypeOf(data))
-}
-
-func (n namedPipeDialer) CallBrowser(p *msdsn.Config) bool {
-	_, ok := p.ProtocolParameters[n.Protocol()]
-	return !ok
-}
diff --git a/namedpipe/stub.go b/namedpipe/stub.go
deleted file mode 100644
index acf5ed2..0000000
--- a/namedpipe/stub.go
+++ /dev/null
@@ -1,33 +0,0 @@
-//go:build !windows
-// +build !windows
-
-package namedpipe
-
-import (
-	"context"
-	"fmt"
-	"net"
-
-	"github.com/microsoft/go-mssqldb/msdsn"
-)
-
-func (n namedPipeDialer) ParseServer(server string, p *msdsn.Config) error {
-	return fmt.Errorf("Named pipe connections are not supported on this operating system")
-}
-
-func (n namedPipeDialer) Protocol() string {
-	return "np"
-}
-
-func (n namedPipeDialer) ParseBrowserData(data msdsn.BrowserData, p *msdsn.Config) error {
-	return fmt.Errorf("Named pipe connections are not supported on this operating system")
-}
-
-func (n namedPipeDialer) DialConnection(ctx context.Context, p msdsn.Config) (conn net.Conn, err error) {
-
-	return nil, fmt.Errorf("Named pipe connections are not supported on this operating system")
-}
-
-func (n namedPipeDialer) CallBrowser(p *msdsn.Config) bool {
-	return false
-}
diff --git a/integratedauth/ntlm/ntlm.go b/ntlm.go
similarity index 94%
rename from integratedauth/ntlm/ntlm.go
rename to ntlm.go
index d95032f..90adb5a 100644
--- a/integratedauth/ntlm/ntlm.go
+++ b/ntlm.go
@@ -1,4 +1,6 @@
-package ntlm
+// +build !windows
+
+package mssql
 
 import (
 	"crypto/des"
@@ -12,9 +14,6 @@ import (
 	"time"
 	"unicode/utf16"
 
-	"github.com/microsoft/go-mssqldb/integratedauth"
-	"github.com/microsoft/go-mssqldb/msdsn"
-
 	//lint:ignore SA1019 MD4 is used by legacy NTLM
 	"golang.org/x/crypto/md4"
 )
@@ -57,26 +56,24 @@ const _NEGOTIATE_FLAGS = _NEGOTIATE_UNICODE |
 	_NEGOTIATE_ALWAYS_SIGN |
 	_NEGOTIATE_EXTENDED_SESSIONSECURITY
 
-type Auth struct {
+type ntlmAuth struct {
 	Domain      string
 	UserName    string
 	Password    string
 	Workstation string
 }
 
-// getAuth returns an authentication handle Auth to provide authentication content
-// to mssql.connect
-func getAuth(config msdsn.Config) (integratedauth.IntegratedAuthenticator, error) {
-	if !strings.ContainsRune(config.User, '\\') {
-		return nil, fmt.Errorf("ntlm : invalid username %v", config.User)
+func getAuth(user, password, service, workstation string) (auth, bool) {
+	if !strings.ContainsRune(user, '\\') {
+		return nil, false
 	}
-	domainUser := strings.SplitN(config.User, "\\", 2)
-	return &Auth{
-		Domain:      domainUser[0],
-		UserName:    domainUser[1],
-		Password:    config.Password,
-		Workstation: config.Workstation,
-	}, nil
+	domain_user := strings.SplitN(user, "\\", 2)
+	return &ntlmAuth{
+		Domain:      domain_user[0],
+		UserName:    domain_user[1],
+		Password:    password,
+		Workstation: workstation,
+	}, true
 }
 
 func utf16le(val string) []byte {
@@ -93,7 +90,7 @@ func utf16le(val string) []byte {
 	return v
 }
 
-func (auth *Auth) InitialBytes() ([]byte, error) {
+func (auth *ntlmAuth) InitialBytes() ([]byte, error) {
 	domain_len := len(auth.Domain)
 	workstation_len := len(auth.Workstation)
 	msg := make([]byte, 40+domain_len+workstation_len)
@@ -361,7 +358,7 @@ func buildNTLMResponsePayload(lm, nt []byte, flags uint32, domain, workstation,
 	return msg, nil
 }
 
-func (auth *Auth) NextBytes(bytes []byte) ([]byte, error) {
+func (auth *ntlmAuth) NextBytes(bytes []byte) ([]byte, error) {
 	signature := string(bytes[0:8])
 	if signature != "NTLMSSP\x00" {
 		return nil, errorNTLM
@@ -392,5 +389,5 @@ func (auth *Auth) NextBytes(bytes []byte) ([]byte, error) {
 	return buildNTLMResponsePayload(lm, nt, flags, auth.Domain, auth.Workstation, auth.UserName)
 }
 
-func (auth *Auth) Free() {
+func (auth *ntlmAuth) Free() {
 }
diff --git a/protocol.go b/protocol.go
deleted file mode 100644
index a3d3513..0000000
--- a/protocol.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package mssql
-
-import (
-	"context"
-	"fmt"
-	"net"
-	"strconv"
-	"strings"
-
-	"github.com/microsoft/go-mssqldb/msdsn"
-)
-
-type MssqlProtocolDialer interface {
-	// DialSqlConnection creates a net.Conn from a Connector based on the Config
-	DialSqlConnection(ctx context.Context, c *Connector, p msdsn.Config) (conn net.Conn, err error)
-}
-
-type tcpDialer struct{}
-
-func (t tcpDialer) ParseBrowserData(data msdsn.BrowserData, p *msdsn.Config) error {
-	// If instance is specified, but no port, check SQL Server Browser
-	// for the instance and discover its port.
-	p.Instance = strings.ToUpper(p.Instance)
-	strport, ok := data[p.Instance]["tcp"]
-	if !ok {
-		f := "no instance matching '%v' returned from host '%v'"
-		return fmt.Errorf(f, p.Instance, p.Host)
-	}
-	port, err := strconv.ParseUint(strport, 0, 16)
-	if err != nil {
-		f := "invalid tcp port returned from Sql Server Browser '%v': %v"
-		return fmt.Errorf(f, strport, err.Error())
-	}
-	p.Port = port
-	return nil
-}
-
-func (t tcpDialer) DialConnection(ctx context.Context, p msdsn.Config) (conn net.Conn, err error) {
-	return nil, fmt.Errorf("tcp dialer requires a Connector instance")
-}
-
-// SQL Server AlwaysOn Availability Group Listeners are bound by DNS to a
-// list of IP addresses.  So if there is more than one, try them all and
-// use the first one that allows a connection.
-func (t tcpDialer) DialSqlConnection(ctx context.Context, c *Connector, p msdsn.Config) (conn net.Conn, err error) {
-	var ips []net.IP
-	ip := net.ParseIP(p.Host)
-	if ip == nil {
-		ips, err = net.LookupIP(p.Host)
-		if err != nil {
-			return
-		}
-	} else {
-		ips = []net.IP{ip}
-	}
-	if len(ips) == 1 {
-		d := c.getDialer(&p)
-		addr := net.JoinHostPort(ips[0].String(), strconv.Itoa(int(resolveServerPort(p.Port))))
-		conn, err = d.DialContext(ctx, "tcp", addr)
-
-	} else {
-		//Try Dials in parallel to avoid waiting for timeouts.
-		connChan := make(chan net.Conn, len(ips))
-		errChan := make(chan error, len(ips))
-		portStr := strconv.Itoa(int(resolveServerPort(p.Port)))
-		for _, ip := range ips {
-			go func(ip net.IP) {
-				d := c.getDialer(&p)
-				addr := net.JoinHostPort(ip.String(), portStr)
-				conn, err := d.DialContext(ctx, "tcp", addr)
-				if err == nil {
-					connChan <- conn
-				} else {
-					errChan <- err
-				}
-			}(ip)
-		}
-		// Wait for either the *first* successful connection, or all the errors
-	wait_loop:
-		for i := range ips {
-			select {
-			case conn = <-connChan:
-				// Got a connection to use, close any others
-				go func(n int) {
-					for i := 0; i < n; i++ {
-						select {
-						case conn := <-connChan:
-							conn.Close()
-						case <-errChan:
-						}
-					}
-				}(len(ips) - i - 1)
-				// Remove any earlier errors we may have collected
-				err = nil
-				break wait_loop
-			case err = <-errChan:
-			}
-		}
-	}
-	// Can't do the usual err != nil check, as it is possible to have gotten an error before a successful connection
-	if conn == nil {
-		f := "unable to open tcp connection with host '%v:%v': %v"
-		return nil, fmt.Errorf(f, p.Host, resolveServerPort(p.Port), err.Error())
-	}
-	return conn, err
-}
-
-func (t tcpDialer) CallBrowser(p *msdsn.Config) bool {
-	return len(p.Instance) > 0 && p.Port == 0
-}
-
-func resolveServerPort(port uint64) uint64 {
-	if port == 0 {
-		return defaultServerPort
-	}
-
-	return port
-}
diff --git a/integratedauth/winsspi/winsspi.go b/sspi_windows.go
similarity index 88%
rename from integratedauth/winsspi/winsspi.go
rename to sspi_windows.go
index 195d228..9b5bc68 100644
--- a/integratedauth/winsspi/winsspi.go
+++ b/sspi_windows.go
@@ -1,15 +1,10 @@
-// +build windows
-
-package winsspi
+package mssql
 
 import (
 	"fmt"
 	"strings"
 	"syscall"
 	"unsafe"
-
-	"github.com/microsoft/go-mssqldb/integratedauth"
-	"github.com/microsoft/go-mssqldb/msdsn"
 )
 
 var (
@@ -109,7 +104,7 @@ type SecBufferDesc struct {
 	pBuffers  *SecBuffer
 }
 
-type Auth struct {
+type SSPIAuth struct {
 	Domain   string
 	UserName string
 	Password string
@@ -118,25 +113,23 @@ type Auth struct {
 	ctxt     SecHandle
 }
 
-// getAuth returns an authentication handle Auth to provide authentication content
-// to mssql.connect
-func getAuth(config msdsn.Config) (integratedauth.IntegratedAuthenticator, error) {
-	if config.User == "" {
-		return &Auth{Service: config.ServerSPN}, nil
+func getAuth(user, password, service, workstation string) (auth, bool) {
+	if user == "" {
+		return &SSPIAuth{Service: service}, true
 	}
-	if !strings.ContainsRune(config.User, '\\') {
-		return nil, fmt.Errorf("winsspi : invalid username %v", config.User)
+	if !strings.ContainsRune(user, '\\') {
+		return nil, false
 	}
-	domainUser := strings.SplitN(config.User, "\\", 2)
-	return &Auth{
-		Domain:   domainUser[0],
-		UserName: domainUser[1],
-		Password: config.Password,
-		Service:  config.ServerSPN,
-	}, nil
+	domain_user := strings.SplitN(user, "\\", 2)
+	return &SSPIAuth{
+		Domain:   domain_user[0],
+		UserName: domain_user[1],
+		Password: password,
+		Service:  service,
+	}, true
 }
 
-func (auth *Auth) InitialBytes() ([]byte, error) {
+func (auth *SSPIAuth) InitialBytes() ([]byte, error) {
 	var identity *SEC_WINNT_AUTH_IDENTITY
 	if auth.UserName != "" {
 		identity = &SEC_WINNT_AUTH_IDENTITY{
@@ -209,7 +202,7 @@ func (auth *Auth) InitialBytes() ([]byte, error) {
 	return outbuf[:buf.cbBuffer], nil
 }
 
-func (auth *Auth) NextBytes(bytes []byte) ([]byte, error) {
+func (auth *SSPIAuth) NextBytes(bytes []byte) ([]byte, error) {
 	var in_buf, out_buf SecBuffer
 	var in_desc, out_desc SecBufferDesc
 
@@ -261,7 +254,7 @@ func (auth *Auth) NextBytes(bytes []byte) ([]byte, error) {
 	return outbuf[:out_buf.cbBuffer], nil
 }
 
-func (auth *Auth) Free() {
+func (auth *SSPIAuth) Free() {
 	syscall.Syscall6(sec_fn.DeleteSecurityContext,
 		1,
 		uintptr(unsafe.Pointer(&auth.ctxt)),
diff --git a/tds.go b/tds.go
index abbe063..dbe9527 100644
--- a/tds.go
+++ b/tds.go
@@ -10,17 +10,17 @@ import (
 	"io/ioutil"
 	"net"
 	"sort"
+	"strconv"
 	"strings"
 	"time"
 	"unicode/utf16"
 	"unicode/utf8"
 
-	"github.com/microsoft/go-mssqldb/integratedauth"
-	"github.com/microsoft/go-mssqldb/msdsn"
+	"github.com/denisenkom/go-mssqldb/msdsn"
 )
 
-func parseInstances(msg []byte) msdsn.BrowserData {
-	results := msdsn.BrowserData{}
+func parseInstances(msg []byte) map[string]map[string]string {
+	results := map[string]map[string]string{}
 	if len(msg) > 3 && msg[0] == 5 {
 		out_s := string(msg[3:])
 		tokens := strings.Split(out_s, ";")
@@ -48,8 +48,8 @@ func parseInstances(msg []byte) msdsn.BrowserData {
 	return results
 }
 
-func getInstances(ctx context.Context, d Dialer, address string) (msdsn.BrowserData, error) {
-	conn, err := d.DialContext(ctx, "udp", net.JoinHostPort(address, "1434"))
+func getInstances(ctx context.Context, d Dialer, address string) (map[string]map[string]string, error) {
+	conn, err := d.DialContext(ctx, "udp", address+":1434")
 	if err != nil {
 		return nil, err
 	}
@@ -468,11 +468,16 @@ func str2ucs2(s string) []byte {
 	return ucs2
 }
 
-const (
-	mask64 uint64 = 0xFF80FF80FF80FF80
-	mask32 uint32 = 0xFF80FF80
-	mask16 uint16 = 0xFF80
-)
+func ucs22str(s []byte) (string, error) {
+	if len(s)%2 != 0 {
+		return "", fmt.Errorf("illegal UCS2 string length: %d", len(s))
+	}
+	buf := make([]uint16, len(s)/2)
+	for i := 0; i < len(s); i += 2 {
+		buf[i/2] = binary.LittleEndian.Uint16(s[i:])
+	}
+	return string(utf16.Decode(buf)), nil
+}
 
 func manglePassword(password string) []byte {
 	var ucs2password []byte = str2ucs2(password)
@@ -680,7 +685,7 @@ func writeUsVarChar(w io.Writer, s string) (err error) {
 	return
 }
 
-func readBVarChar(r io.Reader) (string, error) {
+func readBVarChar(r io.Reader) (res string, err error) {
 	numchars, err := readByte(r)
 	if err != nil {
 		return "", err
@@ -836,30 +841,76 @@ func sendAttention(buf *tdsBuffer) error {
 	return buf.FinishPacket()
 }
 
-// Makes an attempt to connect with each available protocol, in order, until one succeeds or the timeout elapses
-func dialConnection(ctx context.Context, c *Connector, p msdsn.Config, logger ContextLogger) (conn net.Conn, err error) {
-	for _, protocol := range p.Protocols {
-		dialer := msdsn.ProtocolDialers[protocol]
-		sqlDialer, ok := dialer.(MssqlProtocolDialer)
-		if logger != nil {
-			logger.Log(ctx, msdsn.LogDebug, "Dialing with protocol "+protocol)
-		}
-		if !ok {
-			conn, err = dialer.DialConnection(ctx, p)
-		} else {
-			conn, err = sqlDialer.DialSqlConnection(ctx, c, p)
+type auth interface {
+	InitialBytes() ([]byte, error)
+	NextBytes([]byte) ([]byte, error)
+	Free()
+}
+
+// SQL Server AlwaysOn Availability Group Listeners are bound by DNS to a
+// list of IP addresses.  So if there is more than one, try them all and
+// use the first one that allows a connection.
+func dialConnection(ctx context.Context, c *Connector, p msdsn.Config) (conn net.Conn, err error) {
+	var ips []net.IP
+	ip := net.ParseIP(p.Host)
+	if ip == nil {
+		ips, err = net.LookupIP(p.Host)
+		if err != nil {
+			return
 		}
-		if err != nil && logger != nil {
-			logger.Log(ctx, msdsn.LogErrors, "Unable to connect with protocol "+protocol+":"+err.Error())
+	} else {
+		ips = []net.IP{ip}
+	}
+	if len(ips) == 1 {
+		d := c.getDialer(&p)
+		addr := net.JoinHostPort(ips[0].String(), strconv.Itoa(int(resolveServerPort(p.Port))))
+		conn, err = d.DialContext(ctx, "tcp", addr)
+
+	} else {
+		//Try Dials in parallel to avoid waiting for timeouts.
+		connChan := make(chan net.Conn, len(ips))
+		errChan := make(chan error, len(ips))
+		portStr := strconv.Itoa(int(resolveServerPort(p.Port)))
+		for _, ip := range ips {
+			go func(ip net.IP) {
+				d := c.getDialer(&p)
+				addr := net.JoinHostPort(ip.String(), portStr)
+				conn, err := d.DialContext(ctx, "tcp", addr)
+				if err == nil {
+					connChan <- conn
+				} else {
+					errChan <- err
+				}
+			}(ip)
 		}
-		if conn != nil {
-			if logger != nil {
-				logger.Log(ctx, msdsn.LogDebug, "Returning connection from protocol "+protocol)
+		// Wait for either the *first* successful connection, or all the errors
+	wait_loop:
+		for i := range ips {
+			select {
+			case conn = <-connChan:
+				// Got a connection to use, close any others
+				go func(n int) {
+					for i := 0; i < n; i++ {
+						select {
+						case conn := <-connChan:
+							conn.Close()
+						case <-errChan:
+						}
+					}
+				}(len(ips) - i - 1)
+				// Remove any earlier errors we may have collected
+				err = nil
+				break wait_loop
+			case err = <-errChan:
 			}
-			return
 		}
 	}
-	return
+	// Can't do the usual err != nil check, as it is possible to have gotten an error before a successful connection
+	if conn == nil {
+		f := "unable to open tcp connection with host '%v:%v': %v"
+		return nil, fmt.Errorf(f, p.Host, resolveServerPort(p.Port), err.Error())
+	}
+	return conn, err
 }
 
 func preparePreloginFields(p msdsn.Config, fe *featureExtFedAuth) map[uint8][]byte {
@@ -920,7 +971,7 @@ func interpretPreloginResponse(p msdsn.Config, fe *featureExtFedAuth, fields map
 	return
 }
 
-func prepareLogin(ctx context.Context, c *Connector, p msdsn.Config, logger ContextLogger, auth integratedauth.IntegratedAuthenticator, fe *featureExtFedAuth, packetSize uint32) (l *login, err error) {
+func prepareLogin(ctx context.Context, c *Connector, p msdsn.Config, logger ContextLogger, auth auth, fe *featureExtFedAuth, packetSize uint32) (l *login, err error) {
 	var typeFlags uint8
 	if p.ReadOnlyIntent {
 		typeFlags |= fReadOnlyIntent
@@ -988,64 +1039,17 @@ func prepareLogin(ctx context.Context, c *Connector, p msdsn.Config, logger Cont
 	return l, nil
 }
 
-func queryBrowser(ctx context.Context, dialCtx context.Context, c *Connector, logger ContextLogger, p *msdsn.Config) error {
-	var instances msdsn.BrowserData
-	var err error
-	pErrors := make(map[string]error)
-	for _, protocol := range p.Protocols {
-		pd, ok := msdsn.ProtocolDialers[protocol]
-		if !ok {
-			return fmt.Errorf("No dialer is configured for protocol '%s'", protocol)
-		}
-		if pd.CallBrowser(p) {
-			if instances == nil {
-				d := c.getDialer(p)
-				instances, err = getInstances(dialCtx, d, p.Host)
-				if err != nil {
-					f := "unable to get instances from Sql Server Browser on host %v: %v"
-					return fmt.Errorf(f, p.Host, err.Error())
-				}
-			}
-			pErr := pd.ParseBrowserData(instances, p)
-			if pErr != nil {
-				pErrors[protocol] = pErr
-				if logger != nil {
-					logger.Log(ctx, msdsn.Log(logErrors), "Removing protocol "+protocol+" from dialers. Error:"+pErr.Error())
-				}
-			}
-		}
-	}
-	// If any dialer got an error parsing instances, remove it from the dialer list
-	// If no dialers are left, return an error
-	if len(pErrors) == len(p.Protocols) {
-		return fmt.Errorf("Unable to find a matching instance for any supported protocol on host %v", p.Host)
-	}
-	if len(pErrors) > 0 {
-		validProtocols := make([]string, len(p.Protocols)-len(pErrors))
-		i := 0
-		for _, protocol := range p.Protocols {
-			_, hasError := pErrors[protocol]
-			if !hasError {
-				validProtocols[i] = protocol
-				i++
-			}
-		}
-	}
-	return nil
-}
-
 func connect(ctx context.Context, c *Connector, logger ContextLogger, p msdsn.Config) (res *tdsSession, err error) {
 	dialCtx := ctx
 	if p.DialTimeout >= 0 {
 		dt := p.DialTimeout
 		if dt == 0 {
-			dt = time.Duration(15*len(p.Protocols)) * time.Second
+			dt = 15 * time.Second
 		}
 		var cancel func()
 		dialCtx, cancel = context.WithTimeout(ctx, dt)
 		defer cancel()
 	}
-
 	// if instance is specified use instance resolution service
 	if len(p.Instance) > 0 && p.Port != 0 && uint64(p.LogFlags)&logDebug != 0 {
 		// both instance name and port specified
@@ -1053,10 +1057,25 @@ func connect(ctx context.Context, c *Connector, logger ContextLogger, p msdsn.Co
 		// you should not provide instance name when you provide port
 		logger.Log(ctx, msdsn.LogDebug, "WARN: You specified both instance name and port in the connection string, port will be used and instance name will be ignored")
 	}
-
-	err = queryBrowser(ctx, dialCtx, c, logger, &p)
-	if err != nil {
-		return nil, err
+	if len(p.Instance) > 0 {
+		p.Instance = strings.ToUpper(p.Instance)
+		d := c.getDialer(&p)
+		instances, err := getInstances(dialCtx, d, p.Host)
+		if err != nil {
+			f := "unable to get instances from Sql Server Browser on host %v: %v"
+			return nil, fmt.Errorf(f, p.Host, err.Error())
+		}
+		strport, ok := instances[p.Instance]["tcp"]
+		if !ok {
+			f := "no instance matching '%v' returned from host '%v'"
+			return nil, fmt.Errorf(f, p.Instance, p.Host)
+		}
+		port, err := strconv.ParseUint(strport, 0, 16)
+		if err != nil {
+			f := "invalid tcp port returned from Sql Server Browser '%v': %v"
+			return nil, fmt.Errorf(f, strport, err.Error())
+		}
+		p.Port = port
 	}
 	if p.Port == 0 {
 		p.Port = defaultServerPort
@@ -1077,7 +1096,7 @@ func connect(ctx context.Context, c *Connector, logger ContextLogger, p msdsn.Co
 	}
 
 initiate_connection:
-	conn, err := dialConnection(dialCtx, c, p, logger)
+	conn, err := dialConnection(dialCtx, c, p)
 	if err != nil {
 		return nil, err
 	}
@@ -1123,7 +1142,7 @@ initiate_connection:
 			if config.DynamicRecordSizingDisabled == false {
 				config = config.Clone()
 
-				// fix for https://github.com/microsoft/go-mssqldb/issues/166
+				// fix for https://github.com/denisenkom/go-mssqldb/issues/166
 				// Go implementation of TLS payload size heuristic algorithm splits single TDS package to multiple TCP segments,
 				// while SQL Server seems to expect one TCP segment per encrypted TDS package.
 				// Setting DynamicRecordSizingDisabled to true disables that algorithm and uses 16384 bytes per TLS package
@@ -1131,7 +1150,7 @@ initiate_connection:
 			}
 		}
 		if config == nil {
-			config, err = msdsn.SetupTLS("", false, p.Host, "")
+			config, err = msdsn.SetupTLS("", false, p.Host)
 			if err != nil {
 				return nil, err
 			}
@@ -1154,17 +1173,11 @@ initiate_connection:
 		}
 	}
 
-	auth, err := integratedauth.GetIntegratedAuthenticator(p)
-	if err != nil {
-		if uint64(p.LogFlags)&logDebug != 0 {
-			logger.Log(ctx, msdsn.LogDebug, fmt.Sprintf("Error while creating integrated authenticator: %v", err))
-		}
-
-		return nil, err
-	}
-
-	if auth != nil {
+	auth, authOk := getAuth(p.User, p.Password, p.ServerSPN, p.Workstation)
+	if authOk {
 		defer auth.Free()
+	} else {
+		auth = nil
 	}
 
 	login, err := prepareLogin(ctx, c, p, logger, auth, fedAuth, uint32(outbuf.PackageSize()))
@@ -1267,3 +1280,11 @@ initiate_connection:
 	}
 	return &sess, nil
 }
+
+func resolveServerPort(port uint64) uint64 {
+	if port == 0 {
+		return defaultServerPort
+	}
+
+	return port
+}
diff --git a/token.go b/token.go
index d8cf772..61c88fc 100644
--- a/token.go
+++ b/token.go
@@ -7,11 +7,10 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
-	"net"
 	"strconv"
 
+	"github.com/denisenkom/go-mssqldb/msdsn"
 	"github.com/golang-sql/sqlexp"
-	"github.com/microsoft/go-mssqldb/msdsn"
 )
 
 //go:generate go run golang.org/x/tools/cmd/stringer -type token
@@ -50,20 +49,6 @@ const (
 	doneSrvError = 0x100
 )
 
-// CurCmd values in done (undocumented)
-const (
-	cmdSelect = 0xc1
-	// cmdInsert     = 0xc3
-	// cmdDelete     = 0xc4
-	// cmdUpdate     = 0xc5
-	// cmdAbort      = 0xd2
-	// cmdBeginXaxt  = 0xd4
-	// cmdEndXact    = 0xd5
-	// cmdBulkInsert = 0xf0
-	// cmdOpenCursor = 0x20
-	// cmdMerge      = 0x117
-)
-
 // ENVCHANGE types
 // http://msdn.microsoft.com/en-us/library/dd303449.aspx
 const (
@@ -660,6 +645,7 @@ func parseReturnValue(r *tdsBuffer) (nv namedValue) {
 }
 
 func processSingleResponse(ctx context.Context, sess *tdsSession, ch chan tokenStruct, outs outputs) {
+	firstResult := true
 	defer func() {
 		if err := recover(); err != nil {
 			if sess.logFlags&logErrors != 0 {
@@ -669,19 +655,12 @@ func processSingleResponse(ctx context.Context, sess *tdsSession, ch chan tokenS
 		}
 		close(ch)
 	}()
-	colsReceived := false
+
 	packet_type, err := sess.buf.BeginRead()
 	if err != nil {
 		if sess.logFlags&logErrors != 0 {
 			sess.logger.Log(ctx, msdsn.LogErrors, fmt.Sprintf("BeginRead failed %v", err))
 		}
-		switch e := err.(type) {
-		case *net.OpError:
-			err = e
-		default:
-			// the named pipe provider returns a raw win32 error so fake an OpError
-			err = &net.OpError{Op: "Read", Err: err}
-		}
 		ch <- err
 		return
 	}
@@ -718,26 +697,18 @@ func processSingleResponse(ctx context.Context, sess *tdsSession, ch chan tokenS
 			done := parseDoneInProc(sess.buf)
 
 			ch <- done
-			if done.Status&doneCount != 0 {
-				if sess.logFlags&logRows != 0 {
-					sess.logger.Log(ctx, msdsn.LogRows, fmt.Sprintf("(%d rows affected)", done.RowCount))
-				}
+			if sess.logFlags&logRows != 0 && done.Status&doneCount != 0 {
+				sess.logger.Log(ctx, msdsn.LogRows, fmt.Sprintf("(%d rows affected)", done.RowCount))
 
-				if (colsReceived || done.CurCmd != cmdSelect) && outs.msgq != nil {
+				if outs.msgq != nil {
 					_ = sqlexp.ReturnMessageEnqueue(ctx, outs.msgq, sqlexp.MsgRowsAffected{Count: int64(done.RowCount)})
 				}
 			}
-			if outs.msgq != nil {
-				// For now we ignore ctx->Done errors that ReturnMessageEnqueue might return
-				// It's not clear how to handle them correctly here, and data/sql seems
-				// to set Rows.Err correctly when ctx expires already
-				_ = sqlexp.ReturnMessageEnqueue(ctx, outs.msgq, sqlexp.MsgNextResultSet{})
-			}
-			colsReceived = false
 			if done.Status&doneMore == 0 {
-				// Rows marks the request as done when seeing this done token. We queue another result set message
-				// so the app calls NextResultSet again which will return false.
 				if outs.msgq != nil {
+					// For now we ignore ctx->Done errors that ReturnMessageEnqueue might return
+					// It's not clear how to handle them correctly here, and data/sql seems
+					// to set Rows.Err correctly when ctx expires already
 					_ = sqlexp.ReturnMessageEnqueue(ctx, outs.msgq, sqlexp.MsgNextResultSet{})
 				}
 				return
@@ -758,24 +729,16 @@ func processSingleResponse(ctx context.Context, sess *tdsSession, ch chan tokenS
 				}
 				return
 			}
+			if sess.logFlags&logRows != 0 && done.Status&doneCount != 0 {
+				sess.logger.Log(ctx, msdsn.LogRows, fmt.Sprintf("(%d row(s) affected)", done.RowCount))
+			}
 			ch <- done
 			if done.Status&doneCount != 0 {
-				if sess.logFlags&logRows != 0 {
-					sess.logger.Log(ctx, msdsn.LogRows, fmt.Sprintf("(%d row(s) affected)", done.RowCount))
-				}
-
-				if (colsReceived || done.CurCmd != cmdSelect) && outs.msgq != nil {
+				if outs.msgq != nil {
 					_ = sqlexp.ReturnMessageEnqueue(ctx, outs.msgq, sqlexp.MsgRowsAffected{Count: int64(done.RowCount)})
 				}
-
-			}
-			colsReceived = false
-			if outs.msgq != nil {
-				_ = sqlexp.ReturnMessageEnqueue(ctx, outs.msgq, sqlexp.MsgNextResultSet{})
 			}
 			if done.Status&doneMore == 0 {
-				// Rows marks the request as done when seeing this done token. We queue another result set message
-				// so the app calls NextResultSet again which will return false.
 				if outs.msgq != nil {
 					_ = sqlexp.ReturnMessageEnqueue(ctx, outs.msgq, sqlexp.MsgNextResultSet{})
 				}
@@ -784,10 +747,14 @@ func processSingleResponse(ctx context.Context, sess *tdsSession, ch chan tokenS
 		case tokenColMetadata:
 			columns = parseColMetadata72(sess.buf)
 			ch <- columns
-			colsReceived = true
+
 			if outs.msgq != nil {
+				if !firstResult {
+					_ = sqlexp.ReturnMessageEnqueue(ctx, outs.msgq, sqlexp.MsgNextResultSet{})
+				}
 				_ = sqlexp.ReturnMessageEnqueue(ctx, outs.msgq, sqlexp.MsgNext{})
 			}
+			firstResult = false
 
 		case tokenRow:
 			row := make([]interface{}, len(columns))
diff --git a/tvp_go19.go b/tvp_go19.go
index 32485a1..0d55547 100644
--- a/tvp_go19.go
+++ b/tvp_go19.go
@@ -1,3 +1,4 @@
+//go:build go1.9
 // +build go1.9
 
 package mssql
@@ -16,6 +17,7 @@ import (
 const (
 	jsonTag      = "json"
 	tvpTag       = "tvp"
+	tvpIdentity  = "@identity"
 	skipTagValue = "-"
 	sqlSeparator = "."
 )
@@ -29,7 +31,7 @@ var (
 	ErrorWrongTyping      = errors.New("the number of elements in columnStr and tvpFieldIndexes do not align")
 )
 
-//TVP is driver type, which allows supporting Table Valued Parameters (TVP) in SQL Server
+// TVP is driver type, which allows supporting Table Valued Parameters (TVP) in SQL Server
 type TVP struct {
 	//TypeName mustn't be default value
 	TypeName string
@@ -76,8 +78,8 @@ func (tvp TVP) encode(schema, name string, columnStr []columnStruct, tvpFieldInd
 	binary.Write(buf, binary.LittleEndian, uint16(len(columnStr)))
 
 	for i, column := range columnStr {
-		binary.Write(buf, binary.LittleEndian, uint32(column.UserType))
-		binary.Write(buf, binary.LittleEndian, uint16(column.Flags))
+		binary.Write(buf, binary.LittleEndian, column.UserType)
+		binary.Write(buf, binary.LittleEndian, column.Flags)
 		writeTypeInfo(buf, &columnStr[i].ti)
 		writeBVarChar(buf, "")
 	}
@@ -96,6 +98,9 @@ func (tvp TVP) encode(schema, name string, columnStr []columnStruct, tvpFieldInd
 		refStr := reflect.ValueOf(val.Index(i).Interface())
 		buf.WriteByte(_TVP_ROW_TOKEN)
 		for columnStrIdx, fieldIdx := range tvpFieldIndexes {
+			if columnStr[columnStrIdx].Flags == fDefault {
+				continue
+			}
 			field := refStr.Field(fieldIdx)
 			tvpVal := field.Interface()
 			if tvp.verifyStandardTypeOnNull(buf, tvpVal) {
@@ -135,6 +140,11 @@ func (tvp TVP) encode(schema, name string, columnStr []columnStruct, tvpFieldInd
 }
 
 func (tvp TVP) columnTypes() ([]columnStruct, []int, error) {
+	type fieldDetailStore struct {
+		defaultValue interface{}
+		isIdentity   bool
+	}
+
 	val := reflect.ValueOf(tvp.Value)
 	var firstRow interface{}
 	if val.Len() != 0 {
@@ -145,7 +155,7 @@ func (tvp TVP) columnTypes() ([]columnStruct, []int, error) {
 
 	tvpRow := reflect.TypeOf(firstRow)
 	columnCount := tvpRow.NumField()
-	defaultValues := make([]interface{}, 0, columnCount)
+	defaultValues := make([]fieldDetailStore, 0, columnCount)
 	tvpFieldIndexes := make([]int, 0, columnCount)
 	for i := 0; i < columnCount; i++ {
 		field := tvpRow.Field(i)
@@ -155,12 +165,19 @@ func (tvp TVP) columnTypes() ([]columnStruct, []int, error) {
 			continue
 		}
 		tvpFieldIndexes = append(tvpFieldIndexes, i)
+		isIdentity := tvpTagValue == tvpIdentity
 		if field.Type.Kind() == reflect.Ptr {
 			v := reflect.New(field.Type.Elem())
-			defaultValues = append(defaultValues, v.Interface())
+			defaultValues = append(defaultValues, fieldDetailStore{
+				defaultValue: v.Interface(),
+				isIdentity:   isIdentity,
+			})
 			continue
 		}
-		defaultValues = append(defaultValues, tvp.createZeroType(reflect.Zero(field.Type).Interface()))
+		defaultValues = append(defaultValues, fieldDetailStore{
+			defaultValue: tvp.createZeroType(reflect.Zero(field.Type).Interface()),
+			isIdentity:   isIdentity,
+		})
 	}
 
 	if columnCount-len(tvpFieldIndexes) == columnCount {
@@ -176,9 +193,9 @@ func (tvp TVP) columnTypes() ([]columnStruct, []int, error) {
 
 	columnConfiguration := make([]columnStruct, 0, columnCount)
 	for index, val := range defaultValues {
-		cval, err := convertInputParameter(val)
+		cval, err := convertInputParameter(val.defaultValue)
 		if err != nil {
-			return nil, nil, fmt.Errorf("failed to convert tvp parameter row %d col %d: %s", index, val, err)
+			return nil, nil, fmt.Errorf("failed to convert tvp parameter row %d col %d: %s", index, val.defaultValue, err)
 		}
 		param, err := stmt.makeParam(cval)
 		if err != nil {
@@ -187,6 +204,9 @@ func (tvp TVP) columnTypes() ([]columnStruct, []int, error) {
 		column := columnStruct{
 			ti: param.ti,
 		}
+		if val.isIdentity {
+			column.Flags = fDefault
+		}
 		switch param.ti.TypeId {
 		case typeNVarChar, typeBigVarBin:
 			column.ti.Size = 0
diff --git a/types.go b/types.go
index 8780341..cf9640e 100644
--- a/types.go
+++ b/types.go
@@ -10,8 +10,8 @@ import (
 	"strconv"
 	"time"
 
-	"github.com/microsoft/go-mssqldb/internal/cp"
-	"github.com/microsoft/go-mssqldb/internal/decimal"
+	"github.com/denisenkom/go-mssqldb/internal/cp"
+	"github.com/denisenkom/go-mssqldb/internal/decimal"
 )
 
 // fixed-length data types
@@ -79,6 +79,12 @@ const _PLP_TERMINATOR = 0x00000000
 const _TVP_END_TOKEN = 0x00
 const _TVP_ROW_TOKEN = 0x01
 
+// TVP_COLMETADATA definition
+// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tds/0dfc5367-a388-4c92-9ba4-4d28e775acbc
+const (
+	fDefault = 0x200
+)
+
 // TYPE_INFO rule
 // http://msdn.microsoft.com/en-us/library/dd358284.aspx
 type typeInfo struct {
@@ -1353,12 +1359,13 @@ func makeGoLangTypeName(ti typeInfo) string {
 // not a variable length type ok should return false.
 // If length is not limited other than system limits, it should return math.MaxInt64.
 // The following are examples of returned values for various types:
-//   TEXT          (math.MaxInt64, true)
-//   varchar(10)   (10, true)
-//   nvarchar(10)  (10, true)
-//   decimal       (0, false)
-//   int           (0, false)
-//   bytea(30)     (30, true)
+//
+//	TEXT          (math.MaxInt64, true)
+//	varchar(10)   (10, true)
+//	nvarchar(10)  (10, true)
+//	decimal       (0, false)
+//	int           (0, false)
+//	bytea(30)     (30, true)
 func makeGoLangTypeLength(ti typeInfo) (int64, bool) {
 	switch ti.TypeId {
 	case typeInt1:
@@ -1476,12 +1483,13 @@ func makeGoLangTypeLength(ti typeInfo) (int64, bool) {
 // not a variable length type ok should return false.
 // If length is not limited other than system limits, it should return math.MaxInt64.
 // The following are examples of returned values for various types:
-//   TEXT          (math.MaxInt64, true)
-//   varchar(10)   (10, true)
-//   nvarchar(10)  (10, true)
-//   decimal       (0, false)
-//   int           (0, false)
-//   bytea(30)     (30, true)
+//
+//	TEXT          (math.MaxInt64, true)
+//	varchar(10)   (10, true)
+//	nvarchar(10)  (10, true)
+//	decimal       (0, false)
+//	int           (0, false)
+//	bytea(30)     (30, true)
 func makeGoLangTypePrecisionScale(ti typeInfo) (int64, int64, bool) {
 	switch ti.TypeId {
 	case typeInt1:
@@ -1543,13 +1551,13 @@ func makeGoLangTypePrecisionScale(ti typeInfo) (int64, int64, bool) {
 			panic("invalid size of DATETIMEN")
 		}
 	case typeDateTime2N:
-		return int64(ti.Prec), int64(ti.Scale), true
+		return 0, 0, false
 	case typeDateN:
 		return 0, 0, false
 	case typeTimeN:
-		return int64(ti.Prec), int64(ti.Scale), true
+		return 0, 0, false
 	case typeDateTimeOffsetN:
-		return int64(ti.Prec), int64(ti.Scale), true
+		return 0, 0, false
 	case typeBigVarBin:
 		return 0, 0, false
 	case typeVarChar:
diff --git a/ucs22str.go b/ucs22str.go
deleted file mode 100644
index 9c9c66e..0000000
--- a/ucs22str.go
+++ /dev/null
@@ -1,151 +0,0 @@
-//go:build !386 && !arm
-// +build !386,!arm
-
-package mssql
-
-import (
-	"fmt"
-	"reflect"
-	"unicode/utf16"
-	"unsafe"
-)
-
-func ucs22str(s []byte) (string, error) {
-	if len(s)%2 != 0 {
-		return "", fmt.Errorf("illegal UCS2 string length: %d", len(s))
-	}
-
-	// allocate a buffer which we will attempt to copy ascii into, optimistically, as we validate
-	buf := make([]byte, len(s)/2)
-	useFastPath := true
-
-	// how many 8 byte chunks are in the input buffer
-	nlen8 := len(s) & 0xFFFFFFF8
-	// our read and write offsets into the buffers
-	var (
-		readIndex  int
-		writeIndex int
-	)
-
-	// step through in 8 byte chunks.
-	for readIndex = 0; readIndex < nlen8; readIndex += 8 {
-
-		// dereference directly into the array as uint64s
-		ui64 := *(*uint64)(unsafe.Pointer(uintptr(unsafe.Pointer(&s[0])) + uintptr(readIndex)))
-
-		// mask the entire 64 bit region and check for
-		// 1) even bytes > 0
-		// 2) odd bytes with their high bit set
-		// the mask for this is FF80....
-		if ui64&mask64 > 0 {
-			// if we find a value once masked, we have to take the slow path as this is not an ascii string
-			useFastPath = false
-			break
-		}
-
-		// we are ok to read out the 4 odd bytes and remove the empty even bytes
-		var ui32 uint32 = 0
-		ui32 |= uint32(byte(ui64))
-		ui64 = ui64 >> 8
-
-		ui32 |= uint32(uint16(ui64))
-		ui64 = ui64 >> 8
-
-		ui32 |= uint32(ui64 & 0xFF0000)
-		ui64 = ui64 >> 8
-		ui32 |= uint32(ui64 & 0xFF000000)
-
-		// write the new 32 bit value to the destination buffer
-		ptrui32 := ((*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&buf[0])) + uintptr(writeIndex))))
-		*ptrui32 = ui32
-
-		// step forward four bytes in the destinaiton buffer
-		writeIndex += 4
-	}
-
-	// can we continue reading on the fast ascii path?
-	if useFastPath {
-		// we have now dealt with all the avalable 8 byte chunks, we have at most 7 bytes remaining.
-
-		// have we got at least 4 bytes remaining to be read?
-		if len(s)-readIndex >= 4 {
-			// deal with the next 32 bit region
-
-			// read 32 bits from the current read position in the source slice
-			ui32 := *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&s[0])) + uintptr(readIndex)))
-
-			// mask the 32 bit value as above. again, if we find a value
-			// this is not ascii and we need to fall back to the slow path
-			// this time with a 32 bit mask
-			if ui32&mask32 > 0 {
-				// we have found non ascii text and must fallback
-				useFastPath = false
-			} else {
-
-				// read the two odd positions bytes and write as a single 16 bit value
-				var ui16 uint16 = 0
-				ui16 |= uint16(byte(ui32))
-				ui32 = ui32 >> 8
-
-				ui16 |= uint16(ui32)
-
-				ptrui16 := ((*uint16)(unsafe.Pointer(uintptr(unsafe.Pointer(&buf[0])) + uintptr((writeIndex)))))
-				*ptrui16 = ui16
-
-				// step forward the read and write positions.
-				readIndex += 4
-				writeIndex += 2
-			}
-		}
-
-		// Are we still on the fast path?
-		if useFastPath {
-			// have we got at least 2 bytes remaining to be read?
-			// actually we can only have at most 2 bytes at this point
-			// since we know the source buffer has even length.
-			if len(s)-readIndex >= 2 {
-
-				// read 2 bytes
-				ui16 := *(*uint16)(unsafe.Pointer(uintptr(unsafe.Pointer(&s[0])) + uintptr(readIndex)))
-
-				// mask again, but only 16bits
-				if ui16&mask16 == 0 {
-					// manually pull out the low byte and write to our destination buffer
-					buf[writeIndex] = byte(ui16 & 0xFF)
-					// we have now successfully read the entire ascii buffer and can convert to a string
-					return *(*string)(unsafe.Pointer(&buf)), nil
-				}
-			} else {
-				// there were no further bytes to read, but we have successfully read the ascii
-				// and can convert to a string
-				return *(*string)(unsafe.Pointer(&buf)), nil
-			}
-		}
-	}
-
-	// one of the above checks has found non ascii values in the buffer, either
-	// a high bit set in an odd byte or any non zero in an even byte.
-	// we fall back to a slower conversion here.
-
-	// we can reuse the underlying array and create our own uint16 slice here
-	// because utf16.Decode allocates a new buffer and only reads its input.
-
-	// declare a real uint16 slice so that the compiler can keep track of
-	// the underlying memory as we transfer & convert it.
-	// This is to ensure that the GC does not prematurely collect our data.
-	var uint16slice []uint16
-
-	uint16Header := (*reflect.SliceHeader)(unsafe.Pointer(&uint16slice))
-	sourceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&s))
-
-	uint16Header.Data = sourceHeader.Data
-	// it is important to reference s after the assignment of the Data
-	// pointer to make sure that s is not garbage collected before
-	// we have another reference to the data.
-	uint16Header.Len = len(s) / 2       // the output is half the length in bytes
-	uint16Header.Cap = uint16Header.Len // the capacity is also half the number of bytes
-
-	// decode the uint16s as utf-16 and return a string.
-	// After this point both s and uint16slice can be garbage collected.
-	return string(utf16.Decode(uint16slice)), nil
-}
diff --git a/ucs22str_32bit.go b/ucs22str_32bit.go
deleted file mode 100644
index 22ef73b..0000000
--- a/ucs22str_32bit.go
+++ /dev/null
@@ -1,21 +0,0 @@
-//go:build arm || 386
-// +build arm 386
-
-package mssql
-
-import (
-	"encoding/binary"
-	"fmt"
-	"unicode/utf16"
-)
-
-func ucs22str(s []byte) (string, error) {
-	if len(s)%2 != 0 {
-		return "", fmt.Errorf("illegal UCS2 string length: %d", len(s))
-	}
-	buf := make([]uint16, len(s)/2)
-	for i := 0; i < len(s); i += 2 {
-		buf[i/2] = binary.LittleEndian.Uint16(s[i:])
-	}
-	return string(utf16.Decode(buf)), nil
-}


Test patch:
diff --git a/accesstokenconnector_test.go b/accesstokenconnector_test.go
index 303c531..52940fc 100644
--- a/accesstokenconnector_test.go
+++ b/accesstokenconnector_test.go
@@ -1,4 +1,3 @@
-//go:build go1.10
 // +build go1.10
 
 package mssql
@@ -80,7 +79,7 @@ func TestNewAccessTokenConnector(t *testing.T) {
 
 func TestAccessTokenConnectorFailsToConnectIfNoAccessToken(t *testing.T) {
 	errorText := "This is a test"
-	dsn := "Server=tcp:server.database.windows.net;Database=db"
+	dsn := "Server=server.database.windows.net;Database=db"
 	tp := func() (string, error) { return "", errors.New(errorText) }
 	sut, err := NewAccessTokenConnector(dsn, tp)
 	if err != nil {
diff --git a/azuread/azuread_test.go b/azuread/azuread_test.go
index c8faf81..ba7de67 100644
--- a/azuread/azuread_test.go
+++ b/azuread/azuread_test.go
@@ -1,6 +1,3 @@
-//go:build go1.18
-// +build go1.18
-
 package azuread
 
 import (
@@ -10,7 +7,7 @@ import (
 	"os"
 	"testing"
 
-	mssql "github.com/microsoft/go-mssqldb"
+	mssql "github.com/denisenkom/go-mssqldb"
 )
 
 func TestAzureSqlAuth(t *testing.T) {
diff --git a/azuread/configuration_test.go b/azuread/configuration_test.go
index e830d17..04ba9aa 100644
--- a/azuread/configuration_test.go
+++ b/azuread/configuration_test.go
@@ -1,18 +1,15 @@
-//go:build go1.18
-// +build go1.18
-
 package azuread
 
 import (
-	"reflect"
 	"testing"
 
-	mssql "github.com/microsoft/go-mssqldb"
-	"github.com/microsoft/go-mssqldb/msdsn"
+	mssql "github.com/denisenkom/go-mssqldb"
+	"github.com/denisenkom/go-mssqldb/msdsn"
 )
 
 func TestValidateParameters(t *testing.T) {
 	passphrase := "somesecret"
+	accessToken := "some-access-token"
 	certificatepath := "/user/cert/cert.pfx"
 	appid := "applicationclientid=someguid"
 	certprop := "clientcertpath=" + certificatepath
@@ -93,12 +90,13 @@ func TestValidateParameters(t *testing.T) {
 			},
 		},
 		{
-			name: "managed identity with resource id",
-			dsn:  "server=someserver.database.windows.net;fedauth=ActiveDirectoryManagedIdentity;resource id=/subscriptions/{guid}/resourceGroups/{resource-group-name}/{resource-provider-namespace}/{resource-type}/{resource-name}",
+			name: "application with access token",
+			dsn:  "server=someserver.database.windows.net;fedauth=ActiveDirectoryServicePrincipalAccessToken;password=some-access-token;",
 			expected: &azureFedAuthConfig{
-				adalWorkflow:    mssql.FedAuthADALWorkflowMSI,
-				resourceID:      "/subscriptions/{guid}/resourceGroups/{resource-group-name}/{resource-provider-namespace}/{resource-type}/{resource-name}",
-				fedAuthWorkflow: ActiveDirectoryManagedIdentity,
+				password:        accessToken,
+				adalWorkflow:    mssql.FedAuthADALWorkflowNone,
+				fedAuthWorkflow: ActiveDirectoryServicePrincipalAccessToken,
+				fedAuthLibrary: mssql.FedAuthLibrarySecurityToken,
 			},
 		},
 	}
@@ -121,8 +119,9 @@ func TestValidateParameters(t *testing.T) {
 		}
 		// mssqlConfig is not idempotent due to pointers in it, plus we aren't testing its correctness here
 		config.mssqlConfig = msdsn.Config{}
-		if !reflect.DeepEqual(config, tst.expected) {
-			t.Errorf("Captured parameters do not match in test case '%s'. Expected:%+v, Actual:%+v", tst.name, tst.expected, config)
+		if *config != *tst.expected {
+			t.Errorf("Captured parameters do not match in test case '%s'. \nExpected:%+v, \nActual:%+v", tst.name, tst.expected, config)
 		}
 	}
+
 }
diff --git a/bad_server_test.go b/bad_server_test.go
index 2c29c81..46b4be5 100644
--- a/bad_server_test.go
+++ b/bad_server_test.go
@@ -10,7 +10,7 @@ import (
 
 // tests simulating bad server
 
-func testConnectionBad(t *testing.T, connStr string) (err error) {
+func testConnectionBad(t *testing.T, connStr string) {
 	conn, err := sql.Open("mssql", connStr)
 	if err != nil {
 		// should not fail here
@@ -24,8 +24,6 @@ func testConnectionBad(t *testing.T, connStr string) (err error) {
 	if err == nil {
 		t.Fatal("Scan should fail but it succeeded")
 	}
-
-	return
 }
 
 func testBadServer(t *testing.T, handler func(net.Conn)) {
@@ -47,7 +45,7 @@ func testBadServer(t *testing.T, handler func(net.Conn)) {
 	tl := testLogger{t: t}
 	defer tl.StopLogging()
 	SetLogger(&tl)
-	_ = testConnectionBad(t, fmt.Sprintf("host=%s;port=%d;log=255;protocol=tcp", addr.IP.String(), addr.Port))
+	testConnectionBad(t, fmt.Sprintf("host=%s;port=%d;log=255", addr.IP.String(), addr.Port))
 }
 
 func TestBadServerCloseConnection(t *testing.T) {
diff --git a/buf_test.go b/buf_test.go
index 61577c7..5b3b1ec 100644
--- a/buf_test.go
+++ b/buf_test.go
@@ -2,10 +2,8 @@ package mssql
 
 import (
 	"bytes"
-	"encoding/binary"
 	"errors"
 	"testing"
-	"unicode/utf16"
 )
 
 type closableBuffer struct {
@@ -120,165 +118,6 @@ func TestBeginReadSucceeds(t *testing.T) {
 	}
 }
 
-func makeLargeDataBuffer() []byte {
-	data := make([]byte, 1<<15)
-
-	for i := 0; i < len(data); i += 4 {
-		data[i] = 0xFE
-		data[i+1] = 0xDC
-		data[i+2] = 0xBA
-		data[i+3] = 0x89
-	}
-
-	return data
-}
-
-func TestReadUint16Succeeds(t *testing.T) {
-
-	data := makeLargeDataBuffer()
-	size := 0x9 + (1 << 14)
-	buffer := makeBuf(uint16(size), append([]byte{0x01 /*id*/, 0xFF /*status*/, byte((size >> 8) & 0xFF), byte(size & 0xFF) /*size*/, 0xff, 0xff, 0xff, 0xff, 0xff /* byte pattern data to follow */}, data...))
-
-	id, err := buffer.BeginRead()
-	if err != nil {
-		t.Fatal("BeginRead failed:", err.Error())
-	}
-	if id != 1 {
-		t.Fatalf("Expected id to be 1 but it is %d", id)
-	}
-
-	buffer.byte()
-
-	iterations := 0
-
-	defer func() {
-
-		if iterations != (1<<14)/4 {
-			t.Fatalf("Expected to read all data, but only read %v", iterations*4)
-		}
-
-		v := recover()
-		if v == nil {
-			t.Fatalf("Expected EOF but got nil")
-		}
-
-		if err, ok := v.(error); ok {
-			if err.Error() != "Invalid TDS stream: EOF" {
-				t.Fatalf("Expected EOF but got %v", err)
-			}
-		} else {
-			t.Fatalf("Expected EOF but got %v", v)
-		}
-	}()
-
-	for {
-
-		a := buffer.uint16()
-		if a != 0xdcfe {
-			t.Fatalf("Expected read uint16 to be 0xfedc but it is %d", a)
-		}
-
-		b := buffer.uint16()
-		if b != 0x89ba {
-			t.Fatalf("Expected read uint16 to be 0x89ba but it is %d", a)
-		}
-
-		iterations++
-	}
-
-}
-
-func TestReadUint32Succeeds(t *testing.T) {
-
-	data := makeLargeDataBuffer()
-	size := 0x9 + (1 << 14)
-	buffer := makeBuf(uint16(size), append([]byte{0x01 /*id*/, 0xFF /*status*/, byte((size >> 8) & 0xFF), byte(size & 0xFF) /*size*/, 0xff, 0xff, 0xff, 0xff, 0xff /* byte pattern data to follow */}, data...))
-
-	id, err := buffer.BeginRead()
-	if err != nil {
-		t.Fatal("BeginRead failed:", err.Error())
-	}
-	if id != 1 {
-		t.Fatalf("Expected id to be 1 but it is %d", id)
-	}
-
-	buffer.byte()
-
-	iterations := 0
-	defer func() {
-		if iterations != (1<<14)/4 {
-			t.Fatalf("Expected to read all data, but only read %v", iterations*4)
-		}
-
-		v := recover()
-		if v == nil {
-			t.Fatalf("Expected EOF but got nil")
-		}
-
-		if err, ok := v.(error); ok {
-			if err.Error() != "Invalid TDS stream: EOF" {
-				t.Fatalf("Expected EOF but got %v", err)
-			}
-		} else {
-			t.Fatalf("Expected EOF but got %v", v)
-		}
-	}()
-	for {
-		a := buffer.uint32()
-		if a != 0x89badcfe {
-			t.Fatalf("Expected read uint16 to be 0x89badcfe but it is %d", a)
-		}
-
-		iterations++
-	}
-}
-
-func TestReadUint64Succeeds(t *testing.T) {
-
-	data := makeLargeDataBuffer()
-	size := 0x9 + (1 << 14)
-	buffer := makeBuf(uint16(size), append([]byte{0x01 /*id*/, 0xFF /*status*/, byte((size >> 8) & 0xFF), byte(size & 0xFF) /*size*/, 0xff, 0xff, 0xff, 0xff, 0xff /* byte pattern data to follow */}, data...))
-
-	id, err := buffer.BeginRead()
-	if err != nil {
-		t.Fatal("BeginRead failed:", err.Error())
-	}
-	if id != 1 {
-		t.Fatalf("Expected id to be 1 but it is %d", id)
-	}
-
-	buffer.byte()
-
-	iterations := 0
-	defer func() {
-		if iterations != (1<<14)/8 {
-			t.Fatalf("Expected to read all data, but only read %v", iterations*4)
-		}
-
-		v := recover()
-		if v == nil {
-			t.Fatalf("Expected EOF but got nil")
-		}
-
-		if err, ok := v.(error); ok {
-			if err.Error() != "Invalid TDS stream: EOF" {
-				t.Fatalf("Expected EOF but got %v", err)
-			}
-		} else {
-			t.Fatalf("Expected EOF but got %v", v)
-		}
-	}()
-
-	for {
-		a := buffer.uint64()
-		if a != 0x89badcfe89badcfe {
-			t.Fatalf("Expected read uint16 to be 0x89badcfe89badcfe but it is %d", a)
-		}
-
-		iterations++
-	}
-}
-
 func TestReadByteFailsOnSecondPacket(t *testing.T) {
 	buffer := makeBuf(9, []byte{
 		0x01 /*id*/, 0x0 /*not final*/, 0x0, 0x9 /*size*/, 0xff, 0xff, 0xff, 0xff, 0x02, /*test byte*/
@@ -460,88 +299,6 @@ func TestReadUsVarCharOrPanic(t *testing.T) {
 	t.Fatal("UsVarChar() should panic, but it didn't")
 }
 
-func TestReadUsVarCharOrPanicWideChars(t *testing.T) {
-	str := "百度一下，你就知道"
-	runes := utf16.Encode([]rune(str))
-	encodedBytes := make([]byte, len(runes)*2)
-
-	for i := 0; i < len(runes); i++ {
-		binary.LittleEndian.PutUint16(encodedBytes[i*2:], runes[i])
-	}
-
-	memBuf := bytes.NewBuffer(append([]byte{byte(len(runes)), 0}, encodedBytes...))
-
-	s := readUsVarCharOrPanic(memBuf)
-	if s != str {
-		t.Errorf("UsVarChar expected to return %s but it returned %s", str, s)
-	}
-}
-
-func TestReadBVarCharOrPanicWideChars(t *testing.T) {
-	str := "百度一下，你就知道"
-	runes := utf16.Encode([]rune(str))
-	encodedBytes := make([]byte, len(runes)*2)
-
-	for i := 0; i < len(runes); i++ {
-		binary.LittleEndian.PutUint16(encodedBytes[i*2:], runes[i])
-	}
-
-	memBuf := bytes.NewBuffer(append([]byte{byte(len(runes))}, encodedBytes...))
-
-	s := readBVarCharOrPanic(memBuf)
-	if s != str {
-		t.Errorf("UsVarChar expected to return %s but it returned %s", str, s)
-	}
-}
-
-var sideeffectstring string
-
-func BenchmarkReadBVarCharOrPanicWideChars(b *testing.B) {
-	str := "百度一下，你就知道"
-
-	runes := utf16.Encode([]rune(str))
-	encodedBytes := make([]byte, len(runes)*2)
-
-	for i := 0; i < len(runes); i++ {
-		binary.LittleEndian.PutUint16(encodedBytes[i*2:], runes[i])
-	}
-
-	encodedBytes = append([]byte{byte(len(runes))}, encodedBytes...)
-
-	memBuf := bytes.NewReader(encodedBytes)
-
-	for n := 0; n < b.N; n++ {
-
-		s := readBVarCharOrPanic(memBuf)
-		sideeffectstring = s
-
-		memBuf.Reset(encodedBytes)
-	}
-}
-
-func BenchmarkReadBVarCharOrPanicOnly1WideChar(b *testing.B) {
-	str := "abcdefghijklmno百p"
-
-	runes := utf16.Encode([]rune(str))
-	encodedBytes := make([]byte, len(runes)*2)
-
-	for i := 0; i < len(runes); i++ {
-		binary.LittleEndian.PutUint16(encodedBytes[i*2:], runes[i])
-	}
-
-	encodedBytes = append([]byte{byte(len(runes))}, encodedBytes...)
-
-	memBuf := bytes.NewReader(encodedBytes)
-
-	for n := 0; n < b.N; n++ {
-
-		s := readBVarCharOrPanic(memBuf)
-		sideeffectstring = s
-
-		memBuf.Reset(encodedBytes)
-	}
-}
-
 func TestReadBVarCharOrPanic(t *testing.T) {
 	memBuf := bytes.NewBuffer([]byte{3, 0x31, 0, 0x32, 0, 0x33, 0})
 	s := readBVarCharOrPanic(memBuf)
diff --git a/bulkcopy_test.go b/bulkcopy_test.go
index 5de3515..6a63ae2 100644
--- a/bulkcopy_test.go
+++ b/bulkcopy_test.go
@@ -1,5 +1,4 @@
-//go:build go1.9 && !386
-// +build go1.9,!386
+// +build go1.9
 
 package mssql
 
@@ -82,10 +81,6 @@ func TestBulkcopy(t *testing.T) {
 		{"test_binary", []byte("1"), nil},
 		{"test_binary_16", bin, nil},
 		{"test_intvarchar", 1234, "1234"},
-		{"test_int64nvarchar", int64(123456), "123456"},
-		{"test_int32nvarchar", int32(12345), "12345"},
-		{"test_int16nvarchar", int16(1234), "1234"},
-		{"test_int8nvarchar", int8(12), "12"},
 		{"test_intnvarchar", 1234, "1234"},
 	}
 
@@ -283,10 +278,6 @@ func setupTable(ctx context.Context, t *testing.T, conn *sql.Conn, tableName str
 	[test_binary] BINARY NOT NULL,
 	[test_binary_16] BINARY(16) NOT NULL,
 	[test_intvarchar] [varchar](4) NULL,
-	[test_int64nvarchar] [varchar](6) NULL,
-	[test_int32nvarchar] [varchar](5) NULL,
-	[test_int16nvarchar] [varchar](4) NULL,
-	[test_int8nvarchar] [varchar](3) NULL,
 	[test_intnvarchar] [varchar](4) NULL,
  CONSTRAINT [PK_` + tableName + `_id] PRIMARY KEY CLUSTERED
 (
diff --git a/bulkimport_example_test.go b/bulkimport_example_test.go
index 5046c35..4fafbc9 100644
--- a/bulkimport_example_test.go
+++ b/bulkimport_example_test.go
@@ -9,7 +9,7 @@ import (
 	"strings"
 	"unicode/utf8"
 
-	mssql "github.com/microsoft/go-mssqldb"
+	mssql "github.com/denisenkom/go-mssqldb"
 )
 
 const (
diff --git a/datetimeoffset_example_test.go b/datetimeoffset_example_test.go
index 8267b6d..ad419c4 100644
--- a/datetimeoffset_example_test.go
+++ b/datetimeoffset_example_test.go
@@ -9,8 +9,8 @@ import (
 	"log"
 	"time"
 
+	mssql "github.com/denisenkom/go-mssqldb"
 	"github.com/golang-sql/civil"
-	mssql "github.com/microsoft/go-mssqldb"
 )
 
 // This example shows how to insert and retrieve date and time types data
diff --git a/integratedauth/auth_test.go b/integratedauth/auth_test.go
deleted file mode 100644
index a3d25e3..0000000
--- a/integratedauth/auth_test.go
+++ /dev/null
@@ -1,203 +0,0 @@
-package integratedauth
-
-import (
-	"errors"
-	"fmt"
-	"testing"
-
-	"github.com/microsoft/go-mssqldb/msdsn"
-)
-
-const providerName = "stub"
-
-type stubAuth struct {
-	user string
-}
-
-func (s *stubAuth) InitialBytes() ([]byte, error)    { return nil, nil }
-func (s *stubAuth) NextBytes([]byte) ([]byte, error) { return nil, nil }
-func (s *stubAuth) Free()                            {}
-
-func getAuth(config msdsn.Config) (IntegratedAuthenticator, error) {
-	return &stubAuth{config.User}, nil
-}
-
-func TestSetIntegratedAuthenticationProviderReturnsErrOnNilProvider(t *testing.T) {
-	err := SetIntegratedAuthenticationProvider(providerName, nil)
-
-	if err != ErrProviderCannotBeNil {
-		t.Errorf("SetIntegratedAuthenticationProvider() returned err: %v, want %v", err, ErrProviderCannotBeNil)
-	}
-}
-
-func TestSetIntegratedAuthenticationProviderReturnsErrOnEmptyProviderName(t *testing.T) {
-	err := SetIntegratedAuthenticationProvider("", ProviderFunc(getAuth))
-
-	if err != ErrProviderNameMustBePopulated {
-		t.Errorf("SetIntegratedAuthenticationProvider() returned err: %v, want %v", err, ErrProviderNameMustBePopulated)
-	}
-}
-
-func TestSetIntegratedAuthenticationProviderStored(t *testing.T) {
-	err := SetIntegratedAuthenticationProvider(providerName, ProviderFunc(getAuth))
-	if err != nil {
-		t.Errorf("SetIntegratedAuthenticationProvider() returned unexpected err %v", err)
-	}
-	defer removeStubProvider()
-
-	if _, ok := providers[providerName]; !ok {
-		t.Error("SetIntegratedAuthenticationProvider() added provider not found")
-	}
-}
-
-func TestSetIntegratedAuthenticationProviderInstanceIsPassedConnString(t *testing.T) {
-	err := SetIntegratedAuthenticationProvider(providerName, ProviderFunc(getAuth))
-	if err != nil {
-		t.Errorf("SetIntegratedAuthenticationProvider() returned unexpected err %v", err)
-	}
-	defer removeStubProvider()
-
-	config, err := msdsn.Parse(fmt.Sprintf("authenticator=%v;user id=username", providerName))
-	if err != nil {
-		t.Errorf("msdsn.Parse : Unexpected error %v", err)
-		return
-	}
-
-	authenticator, err := GetIntegratedAuthenticator(config)
-
-	if err != nil {
-		t.Errorf("expected GetIntegratedAuthenticator() to return ok, found %v", err)
-	}
-
-	a, ok := authenticator.(*stubAuth)
-	if !ok {
-		t.Errorf("expected result of GetIntegratedAuthenticator() to be an instance of stubAuth")
-	}
-
-	if a.user != "username" {
-		t.Errorf("expected stubAuth username to be correct")
-	}
-}
-
-func TestSetIntegratedAuthenticationProviderInstanceIsDefaultWhenAuthenticatorParamNotPassed(t *testing.T) {
-	removeStubProvider()
-
-	config, err := msdsn.Parse("user id=username")
-	if err != nil {
-		t.Errorf("msdsn.Parse : Unexpected error %v", err)
-		return
-	}
-
-	DefaultProviderName = "DEFAULT_PROVIDER"
-	defer func() { DefaultProviderName = "" }()
-
-	err = SetIntegratedAuthenticationProvider(DefaultProviderName, ProviderFunc(func(config msdsn.Config) (IntegratedAuthenticator, error) {
-		return &stubAuth{"DEFAULT INSTANCE"}, nil
-	}))
-	if err != nil {
-		t.Errorf("SetIntegratedAuthenticationProvider() returned unexpected err %v", err)
-	}
-
-	result, err := GetIntegratedAuthenticator(config)
-
-	if err != nil {
-		t.Errorf("expected GetIntegratedAuthenticator() to return ok, found %v", err)
-	}
-
-	a, ok := result.(*stubAuth)
-	if !ok {
-		t.Errorf("expected result of GetIntegratedAuthenticator() to be an instance of stubAuth")
-	}
-
-	if a.user != "DEFAULT INSTANCE" {
-		t.Errorf("expected GetIntegratedAuthenticator for return DefaultProviderName instance when no authenticator param is passed, found %v", a.user)
-	}
-}
-
-func TestGetIntegratedAuthenticatorFallBackToSqlAuthOnErrorOfDefaultProvider(t *testing.T) {
-	removeStubProvider()
-
-	config, err := msdsn.Parse("user id=username")
-	if err != nil {
-		t.Errorf("msdsn.Parse : Unexpected error %v", err)
-		return
-	}
-
-	DefaultProviderName = "DEFAULT_PROVIDER"
-	defer func() { DefaultProviderName = "" }()
-
-	err = SetIntegratedAuthenticationProvider(DefaultProviderName, ProviderFunc(func(config msdsn.Config) (IntegratedAuthenticator, error) {
-		return nil, errors.New("default authenticator cant continue")
-	}))
-	if err != nil {
-		t.Errorf("SetIntegratedAuthenticationProvider() returned unexpected err %v", err)
-	}
-
-	result, err := GetIntegratedAuthenticator(config)
-
-	if err != nil {
-		t.Errorf("expected GetIntegratedAuthenticator() to return ok, found %v", err)
-	}
-
-	if result != nil {
-		t.Errorf("expected GetIntegratedAuthenticator() to return nill authenticator, found %v", result)
-	}
-}
-
-func TestGetIntegratedAuthenticatorToErrorWhenNoDefaultProviderFound(t *testing.T) {
-	removeStubProvider()
-
-	// dont set an authenticator
-	config, err := msdsn.Parse("user id=username")
-	if err != nil {
-		t.Errorf("msdsn.Parse : Unexpected error %v", err)
-		return
-	}
-
-	DefaultProviderName = "NONEXISTANT_DEFAULT_PROVIDER"
-	defer func() { DefaultProviderName = "" }()
-
-	result, err := GetIntegratedAuthenticator(config)
-
-	if err == nil {
-		t.Error("expected GetIntegratedAuthenticator() to return error, found nil")
-	}
-
-	if result != nil {
-		t.Errorf("expected GetIntegratedAuthenticator() to return nill provider, found %v", result)
-	}
-
-	if err != nil && err.Error() != "provider NONEXISTANT_DEFAULT_PROVIDER not found" {
-		t.Errorf("expected err that default provider was not found, found %v", err)
-	}
-}
-
-func TestGetIntegratedAuthenticatorToErrorWhenNoSpecifiedProviderFound(t *testing.T) {
-	removeStubProvider()
-	defer removeStubProvider()
-
-	config, err := msdsn.Parse("authenticator=NONEXISTANTPROVIDER;user id=username")
-	if err != nil {
-		t.Errorf("msdsn.Parse : Unexpected error %v", err)
-		return
-	}
-
-	// dont set an authenticator
-	result, err := GetIntegratedAuthenticator(config)
-
-	if err == nil {
-		t.Error("expected GetIntegratedAuthenticator() to return error, found nil")
-	}
-
-	if result != nil {
-		t.Errorf("expected GetIntegratedAuthenticator() to return nill provider, found %v", result)
-	}
-
-	if err != nil && err.Error() != "provider NONEXISTANTPROVIDER not found" {
-		t.Errorf("expected err that default provider was not found, found %v", err)
-	}
-}
-
-func removeStubProvider() {
-	delete(providers, providerName)
-}
diff --git a/integratedauth/krb5/krb5_test.go b/integratedauth/krb5/krb5_test.go
deleted file mode 100644
index 5da6596..0000000
--- a/integratedauth/krb5/krb5_test.go
+++ /dev/null
@@ -1,215 +0,0 @@
-//go:build !windows && go1.13
-// +build !windows,go1.13
-
-package krb5
-
-import (
-	"io/ioutil"
-	"reflect"
-	"testing"
-
-	"github.com/jcmturner/gokrb5/v8/client"
-	"github.com/jcmturner/gokrb5/v8/config"
-	"github.com/jcmturner/gokrb5/v8/credentials"
-	"github.com/jcmturner/gokrb5/v8/keytab"
-	"github.com/microsoft/go-mssqldb/integratedauth"
-	"github.com/microsoft/go-mssqldb/msdsn"
-)
-
-func TestGetAuth(t *testing.T) {
-	kerberos := getKerberos()
-	var err error
-	configParams := msdsn.Config{
-		User:      "",
-		ServerSPN: "MSSQLSvc/mssql.domain.com:1433",
-		Port:      1433,
-		Parameters: map[string]string{
-			"krb5conffile": "krb5conffile",
-			"keytabfile":   "keytabfile",
-			"krbcache":     "krbcache",
-			"realm":        "domain.com",
-		},
-	}
-
-	SetKrbConfig = func(krb5configPath string) (*config.Config, error) {
-		return &config.Config{}, nil
-	}
-	SetKrbKeytab = func(keytabFilePath string) (*keytab.Keytab, error) {
-		return &keytab.Keytab{}, nil
-	}
-	SetKrbCache = func(kerbCCahePath string) (*credentials.CCache, error) {
-		return &credentials.CCache{}, nil
-	}
-
-	got, err := getAuth(configParams)
-	if err != nil {
-		t.Errorf("failed:%v", err)
-	}
-	kt := &krb5Auth{username: "",
-		realm:      "domain.com",
-		serverSPN:  "MSSQLSvc/mssql.domain.com:1433",
-		port:       1433,
-		krb5Config: kerberos.Config,
-		krbKeytab:  kerberos.Keytab,
-		krbCache:   kerberos.Cache,
-		state:      0}
-
-	res := reflect.DeepEqual(got, kt)
-	if !res {
-		t.Errorf("Failed to get correct krb5Auth object\nExpected:%v\nRecieved:%v", kt, got)
-	}
-
-	configParams.ServerSPN = "MSSQLSvc/mssql.domain.com"
-
-	_, val := getAuth(configParams)
-	if val == nil {
-		t.Errorf("Failed to get correct krb5Auth object: no port defined")
-	}
-
-	configParams.ServerSPN = "MSSQLSvc/mssql.domain.com:1433@DOMAIN.COM"
-
-	got, _ = getAuth(configParams)
-	kt = &krb5Auth{username: "",
-		realm:      "DOMAIN.COM",
-		serverSPN:  "MSSQLSvc/mssql.domain.com:1433",
-		port:       1433,
-		krb5Config: kerberos.Config,
-		krbKeytab:  kerberos.Keytab,
-		krbCache:   kerberos.Cache,
-		state:      0}
-
-	res = reflect.DeepEqual(got, kt)
-	if !res {
-		t.Errorf("Failed to get correct krb5Auth object\nExpected:%v\nRecieved:%v", kt, got)
-	}
-
-	configParams.ServerSPN = "MSSQLSvc/mssql.domain.com:1433@domain.com@test"
-	_, val = getAuth(configParams)
-	if val == nil {
-		t.Errorf("Failed to get correct krb5Auth object due to incorrect serverSPN name")
-	}
-
-	configParams.ServerSPN = "MSSQLSvc/mssql.domain.com:port@domain.com"
-	_, val = getAuth(configParams)
-	if val == nil {
-		t.Errorf("Failed to get correct krb5Auth object due to incorrect port")
-	}
-
-	configParams.ServerSPN = "MSSQLSvc/mssql.domain.com:port"
-	_, val = getAuth(configParams)
-	if val == nil {
-		t.Errorf("Failed to get correct krb5Auth object due to incorrect port")
-	}
-}
-
-func TestInitialBytes(t *testing.T) {
-	kerberos := getKerberos()
-	krbObj := &krb5Auth{username: "",
-		realm:      "domain.com",
-		serverSPN:  "MSSQLSvc/mssql.domain.com:1433",
-		port:       1433,
-		krb5Config: kerberos.Config,
-		krbKeytab:  kerberos.Keytab,
-		krbCache:   kerberos.Cache,
-		state:      0,
-	}
-
-	_, err := krbObj.InitialBytes()
-	if err == nil {
-		t.Errorf("Initial Bytes expected to fail but it didn't")
-	}
-
-	krbObj.krbKeytab = nil
-	_, err = krbObj.InitialBytes()
-	if err == nil {
-		t.Errorf("Initial Bytes expected to fail but it didn't")
-	}
-
-}
-
-func TestNextBytes(t *testing.T) {
-	ans := []byte{}
-	kerberos := getKerberos()
-
-	var krbObj integratedauth.IntegratedAuthenticator = &krb5Auth{username: "",
-		realm:      "domain.com",
-		serverSPN:  "MSSQLSvc/mssql.domain.com:1433",
-		port:       1433,
-		krb5Config: kerberos.Config,
-		krbKeytab:  kerberos.Keytab,
-		krbCache:   kerberos.Cache,
-		state:      0}
-
-	_, err := krbObj.NextBytes(ans)
-	if err == nil {
-		t.Errorf("Next Byte expected to fail but it didn't")
-	}
-}
-
-func TestFree(t *testing.T) {
-	kerberos := getKerberos()
-	kt := &keytab.Keytab{}
-	c := &config.Config{}
-
-	cl := client.NewWithKeytab("Administrator", "DOMAIN.COM", kt, c, client.DisablePAFXFAST(true))
-
-	var krbObj integratedauth.IntegratedAuthenticator = &krb5Auth{username: "",
-		realm:      "domain.com",
-		serverSPN:  "MSSQLSvc/mssql.domain.com:1433",
-		port:       1433,
-		krb5Config: kerberos.Config,
-		krbKeytab:  kerberos.Keytab,
-		krbCache:   kerberos.Cache,
-		state:      0,
-		krb5Client: cl,
-	}
-	krbObj.Free()
-	cacheEntries := len(kerberos.Cache.GetEntries())
-	if cacheEntries != 0 {
-		t.Errorf("Client not destroyed")
-	}
-}
-
-func TestSetKrbConfig(t *testing.T) {
-	krb5conffile := createTempFile(t, "krb5conffile")
-	_, err := setupKerbConfig(krb5conffile)
-	if err != nil {
-		t.Errorf("Failed to read krb5 config file")
-	}
-}
-
-func TestSetKrbKeytab(t *testing.T) {
-	krbkeytab := createTempFile(t, "keytabfile")
-	_, err := setupKerbKeytab(krbkeytab)
-	if err == nil {
-		t.Errorf("Failed to read keytab file")
-	}
-}
-
-func TestSetKrbCache(t *testing.T) {
-	krbcache := createTempFile(t, "krbcache")
-	_, err := setupKerbCache(krbcache)
-	if err == nil {
-		t.Errorf("Failed to read cache file")
-	}
-}
-
-func getKerberos() (krbParams *Kerberos) {
-	krbParams = &Kerberos{
-		Config: &config.Config{},
-		Keytab: &keytab.Keytab{},
-		Cache:  &credentials.CCache{},
-	}
-	return
-}
-
-func createTempFile(t *testing.T, filename string) string {
-	file, err := ioutil.TempFile("", "test-"+filename+".txt")
-	if err != nil {
-		t.Fatalf("Failed to create a temp file:%v", err)
-	}
-	if _, err := file.Write([]byte("This is a test file\n")); err != nil {
-		t.Fatalf("Failed to write file:%v", err)
-	}
-	return file.Name()
-}
diff --git a/log_test.go b/log_test.go
index 529e283..9ac86d7 100644
--- a/log_test.go
+++ b/log_test.go
@@ -8,7 +8,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/microsoft/go-mssqldb/msdsn"
+	"github.com/denisenkom/go-mssqldb/msdsn"
 )
 
 // bufLogger implements the Logger interface for testing purposes.
diff --git a/messages_example_test.go b/messages_example_test.go
index 99faf3f..37dc0e8 100644
--- a/messages_example_test.go
+++ b/messages_example_test.go
@@ -9,8 +9,8 @@ import (
 	"fmt"
 	"log"
 
+	mssql "github.com/denisenkom/go-mssqldb"
 	"github.com/golang-sql/sqlexp"
-	mssql "github.com/microsoft/go-mssqldb"
 )
 
 const (
diff --git a/msdsn/conn_str_test.go b/msdsn/conn_str_test.go
index 8b0f16f..594b5b3 100644
--- a/msdsn/conn_str_test.go
+++ b/msdsn/conn_str_test.go
@@ -1,7 +1,6 @@
 package msdsn
 
 import (
-	"crypto/tls"
 	"reflect"
 	"testing"
 	"time"
@@ -35,7 +34,7 @@ func TestInvalidConnectionString(t *testing.T) {
 		"sqlserver://host?key=value1&key=value2", // duplicate keys
 	}
 	for _, connStr := range connStrings {
-		_, err := Parse(connStr)
+		_, _, err := Parse(connStr)
 		if err == nil {
 			t.Errorf("Connection expected to fail for connection string %s but it didn't", connStr)
 			continue
@@ -60,23 +59,7 @@ func TestValidConnectionString(t *testing.T) {
 		{"failoverpartner=fopartner;failoverport=2000", func(p Config) bool { return p.FailOverPartner == "fopartner" && p.FailOverPort == 2000 }},
 		{"app name=appname;applicationintent=ReadOnly;database=testdb", func(p Config) bool { return p.AppName == "appname" && p.ReadOnlyIntent }},
 		{"encrypt=disable", func(p Config) bool { return p.Encryption == EncryptionDisabled }},
-		{"encrypt=disable;tlsmin=1.1", func(p Config) bool { return p.Encryption == EncryptionDisabled && p.TLSConfig == nil }},
-		{"encrypt=true", func(p Config) bool { return p.Encryption == EncryptionRequired && p.TLSConfig.MinVersion == 0 }},
-		{"encrypt=true;tlsmin=1.0", func(p Config) bool {
-			return p.Encryption == EncryptionRequired && p.TLSConfig.MinVersion == tls.VersionTLS10
-		}},
-		{"encrypt=false;tlsmin=1.0", func(p Config) bool {
-			return p.Encryption == EncryptionOff && p.TLSConfig.MinVersion == tls.VersionTLS10
-		}},
-		{"encrypt=true;tlsmin=1.1", func(p Config) bool {
-			return p.Encryption == EncryptionRequired && p.TLSConfig.MinVersion == tls.VersionTLS11
-		}},
-		{"encrypt=true;tlsmin=1.2", func(p Config) bool {
-			return p.Encryption == EncryptionRequired && p.TLSConfig.MinVersion == tls.VersionTLS12
-		}},
-		{"encrypt=true;tlsmin=1.4", func(p Config) bool {
-			return p.Encryption == EncryptionRequired && p.TLSConfig.MinVersion == 0
-		}},
+		{"encrypt=true", func(p Config) bool { return p.Encryption == EncryptionRequired }},
 		{"encrypt=false", func(p Config) bool { return p.Encryption == EncryptionOff }},
 		{"connection timeout=3;dial timeout=4;keepalive=5", func(p Config) bool {
 			return p.ConnTimeout == 3*time.Second && p.DialTimeout == 4*time.Second && p.KeepAlive == 5*time.Second
@@ -176,12 +159,9 @@ func TestValidConnectionString(t *testing.T) {
 		{"sqlserver://someuser@somehost?connection+timeout=30&disableretry=1", func(p Config) bool {
 			return p.Host == "somehost" && p.Port == 0 && p.Instance == "" && p.User == "someuser" && p.Password == "" && p.ConnTimeout == 30*time.Second && p.DisableRetry
 		}},
-		{"sqlserver://somehost?encrypt=true&tlsmin=1.1", func(p Config) bool {
-			return p.Host == "somehost" && p.Encryption == EncryptionRequired && p.TLSConfig.MinVersion == tls.VersionTLS11
-		}},
 	}
 	for _, ts := range connStrings {
-		p, err := Parse(ts.connStr)
+		p, _, err := Parse(ts.connStr)
 		if err == nil {
 			t.Logf("Connection string was parsed successfully %s", ts.connStr)
 		} else {
@@ -203,12 +183,12 @@ func TestSplitConnectionStringURL(t *testing.T) {
 }
 
 func TestConnParseRoundTripFixed(t *testing.T) {
-	connStr := "sqlserver://sa:sa@localhost/sqlexpress?database=master&log=127&disableretry=true&dial+timeout=30"
-	params, err := Parse(connStr)
+	connStr := "sqlserver://sa:sa@localhost/sqlexpress?database=master&log=127"
+	params, _, err := Parse(connStr)
 	if err != nil {
 		t.Fatal("Test URL is not valid", err)
 	}
-	rtParams, err := Parse(params.URL().String())
+	rtParams, _, err := Parse(params.URL().String())
 	if err != nil {
 		t.Fatal("Params after roundtrip are not valid", err)
 	}
@@ -216,39 +196,3 @@ func TestConnParseRoundTripFixed(t *testing.T) {
 		t.Fatal("Parameters do not match after roundtrip", params, rtParams)
 	}
 }
-
-func TestAllKeysAreAvailableInParametersMap(t *testing.T) {
-	keys := map[string]string{
-		"user id":            "1",
-		"testparam":          "testvalue",
-		"password":           "test",
-		"thisisanunknownkey": "thisisthevalue",
-		"server":             "name",
-	}
-
-	connString := ""
-	for key, val := range keys {
-		connString += key + "=" + val + ";"
-	}
-
-	params, err := Parse(connString)
-	if err != nil {
-		t.Errorf("unexpected error while parsing, %v", err)
-	}
-
-	if params.Parameters == nil {
-		t.Error("Expected parameters map to be instanciated, found nil")
-		return
-	}
-
-	if len(params.Parameters) != len(keys) {
-		t.Errorf("Expected parameters map to be same length as input map length, expected %v, found %v", len(keys), len(params.Parameters))
-		return
-	}
-
-	for key, val := range keys {
-		if params.Parameters[key] != val {
-			t.Errorf("Expected parameters map to contain key %v and value %v, found %v", key, val, params.Parameters[key])
-		}
-	}
-}
diff --git a/msdsn/protocolparse_test.go b/msdsn/protocolparse_test.go
deleted file mode 100644
index 8ea712c..0000000
--- a/msdsn/protocolparse_test.go
+++ /dev/null
@@ -1,78 +0,0 @@
-package msdsn
-
-import (
-	"fmt"
-	"strings"
-	"testing"
-)
-
-type testProtocol struct{}
-
-var protocolImpl = testProtocol{}
-
-func (t testProtocol) ParseServer(server string, p *Config) error {
-	if strings.HasPrefix(server, "**") {
-		p.ProtocolParameters[t.Protocol()] = "special"
-	}
-	if server == "fail" {
-		return fmt.Errorf("ParseServer fail")
-	}
-	// p.Host is empty if tst protocol was specified
-	if p.Host == "" {
-		p.Host = strings.TrimPrefix(server, "**")
-	}
-	return nil
-}
-
-func (t testProtocol) Protocol() string {
-	return "tst"
-}
-
-func init() {
-	ProtocolParsers = append(ProtocolParsers, protocolImpl)
-}
-
-func TestProtocolParseExtension(t *testing.T) {
-	type tst struct {
-		dsn            string
-		expectedConfig func(c *Config) bool
-	}
-	tests := []tst{
-		{"server=myserver", func(c *Config) bool {
-			return len(c.Protocols) == 2 && c.Protocols[0] == "tcp" && c.Protocols[1] == "tst" && c.Host == "myserver" && c.ProtocolParameters["tst"] == nil
-		}},
-		{"server=**myserver", func(c *Config) bool {
-			return len(c.Protocols) == 2 && c.Protocols[0] == "tcp" && c.Protocols[1] == "tst" && c.Host == "**myserver" && c.ProtocolParameters["tst"] == "special"
-		}},
-		{"server=tst:**myserver", func(c *Config) bool {
-			return len(c.Protocols) == 1 && c.Protocols[0] == "tst" && c.Host == "myserver" && c.ProtocolParameters["tst"] == "special"
-		}},
-		{"server=tst:myserver", func(c *Config) bool {
-			return len(c.Protocols) == 1 && c.Protocols[0] == "tst" && c.Host == "myserver" && c.ProtocolParameters["tst"] == nil
-		}},
-		{"sqlserver://user@myserver", func(c *Config) bool {
-			return len(c.Protocols) == 2 && c.Protocols[0] == "tcp" && c.Protocols[1] == "tst" && c.Host == "myserver" && c.ProtocolParameters["tst"] == nil
-		}},
-		{"sqlserver://**myserver", func(c *Config) bool {
-			return len(c.Protocols) == 2 && c.Protocols[0] == "tcp" && c.Protocols[1] == "tst" && c.Host == "**myserver" && c.ProtocolParameters["tst"] == "special"
-		}},
-		{"sqlserver://**myserver?protocol=tst", func(c *Config) bool {
-			return len(c.Protocols) == 1 && c.Protocols[0] == "tst" && c.Host == "myserver" && c.ProtocolParameters["tst"] == "special"
-		}},
-		{"sqlserver://myserver?protocol=tst", func(c *Config) bool {
-			return len(c.Protocols) == 1 && c.Protocols[0] == "tst" && c.Host == "myserver" && c.ProtocolParameters["tst"] == nil
-		}},
-		{"sqlserver://fail", func(c *Config) bool {
-			return len(c.Protocols) == 1 && c.Protocols[0] == "tcp" && c.Host == "fail" && c.ProtocolParameters["tst"] == nil
-		}},
-	}
-	for _, test := range tests {
-		c, err := Parse(test.dsn)
-		if err != nil {
-			t.Fatalf("Unexpected error parsing '%s':'%s'", test.dsn, err.Error())
-		}
-		if !test.expectedConfig(&c) {
-			t.Fatalf("Config validation failed for '%s'. Config: '%v'", test.dsn, c)
-		}
-	}
-}
diff --git a/mssql_go110_perf_test.go b/mssql_go110_perf_test.go
deleted file mode 100644
index b9ebd29..0000000
--- a/mssql_go110_perf_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-//go:build go1.10
-// +build go1.10
-
-package mssql
-
-import (
-	"database/sql"
-	"testing"
-)
-
-// The default value converter promotes every int type to bigint.
-// This benchmark forces that mismatch for comparing the query performance with the
-// fixed version of the driver that doesn't perform such promotion.
-// It may not show much of a time difference. Look for the actual query via plan or xevents
-// while the benchmark runs to make sure it's passing the correct int type.
-func BenchmarkSelectWithTypeMismatch(b *testing.B) {
-	connector, err := NewConnector(makeConnStr(b).String())
-	if err != nil {
-		b.Fatal("Open connection failed:", err.Error())
-	}
-	conn := sql.OpenDB(connector)
-	defer conn.Close()
-	conn.SetMaxOpenConns(1)
-	conn.SetMaxIdleConns(1)
-	rows, err := conn.Query("select 'prime the pump'")
-	if err != nil {
-		b.Fatal("Unable to query")
-	}
-	rows.Close()
-	if rows.Err() != nil {
-		b.Fatal("Rows error:", rows.Err())
-	}
-	b.Run("PromoteToBigInt", func(b *testing.B) {
-		for i := 0; i < b.N; i++ {
-			rows, err := conn.Query(`SELECT Count(*) from sys.all_objects where object_id > @obid`, sql.Named("obid", int64(-605853368)))
-			if err != nil {
-				b.Fatal("Query failed:", err.Error())
-			}
-			defer rows.Close()
-			for rows.Next() {
-			}
-			if rows.Err() != nil {
-				b.Fatal("Rows error:", rows.Err())
-			}
-		}
-	})
-	b.Run("NoIntPromotion", func(b *testing.B) {
-		for i := 0; i < b.N; i++ {
-			rows, err := conn.Query(`SELECT Count(*) from sys.all_objects where object_id > @obid`, sql.Named("obid", int32(-605853368)))
-			if err != nil {
-				b.Fatal("Query failed:", err.Error())
-			}
-			defer rows.Close()
-			for rows.Next() {
-			}
-			if rows.Err() != nil {
-				b.Fatal("Rows error:", rows.Err())
-			}
-		}
-	})
-
-}
diff --git a/mssql_test.go b/mssql_test.go
index 9c50b83..d1bab1b 100644
--- a/mssql_test.go
+++ b/mssql_test.go
@@ -10,7 +10,7 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/microsoft/go-mssqldb/msdsn"
+	"github.com/denisenkom/go-mssqldb/msdsn"
 )
 
 func TestBadOpen(t *testing.T) {
diff --git a/namedpipe_test.go b/namedpipe_test.go
deleted file mode 100644
index a8fcfe5..0000000
--- a/namedpipe_test.go
+++ /dev/null
@@ -1,16 +0,0 @@
-//go:build np
-// +build np
-
-package mssql
-
-import (
-	"github.com/microsoft/go-mssqldb/msdsn"
-	_ "github.com/microsoft/go-mssqldb/namedpipe"
-	"testing"
-)
-
-func TestNamedPipeProtocolInstalled(t *testing.T) {
-	if len(msdsn.ProtocolParsers) != 2 {
-		t.Fatal("np protocol not registered")
-	}
-}
diff --git a/net_go116_test.go b/net_go116_test.go
index c1b4952..27776d3 100644
--- a/net_go116_test.go
+++ b/net_go116_test.go
@@ -1,4 +1,3 @@
-//go:build go1.16
 // +build go1.16
 
 package mssql
@@ -57,7 +56,6 @@ func TestTimeoutConn(t *testing.T) {
 }
 
 func TestTLSHandshakeConn(t *testing.T) {
-	skipIfNamedPipesEnabled(t)
 	tl := testLogger{t: t}
 	defer tl.StopLogging()
 	SetLogger(&tl)
@@ -70,7 +68,7 @@ func TestTLSHandshakeConn(t *testing.T) {
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
 	defer cancel()
 
-	toconn, err := dialConnection(ctx, connector, connector.params, nil)
+	toconn, err := dialConnection(ctx, connector, connector.params)
 	if err != nil {
 		t.Error(err)
 	}
@@ -117,7 +115,6 @@ func TestTLSHandshakeConn(t *testing.T) {
 }
 
 func TestPassthroughConn(t *testing.T) {
-	skipIfNamedPipesEnabled(t)
 	tl := testLogger{t: t}
 	defer tl.StopLogging()
 	SetLogger(&tl)
@@ -130,7 +127,7 @@ func TestPassthroughConn(t *testing.T) {
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
 	defer cancel()
 
-	toconn, err := dialConnection(ctx, connector, connector.params, nil)
+	toconn, err := dialConnection(ctx, connector, connector.params)
 	if err != nil {
 		t.Error(err)
 	}
diff --git a/newconnector_example_test.go b/newconnector_example_test.go
index 28bfd5a..8dc74ba 100644
--- a/newconnector_example_test.go
+++ b/newconnector_example_test.go
@@ -12,7 +12,7 @@ import (
 	"net/url"
 	"strconv"
 
-	mssql "github.com/microsoft/go-mssqldb"
+	mssql "github.com/denisenkom/go-mssqldb"
 )
 
 var (
diff --git a/integratedauth/ntlm/ntlm_test.go b/ntlm_test.go
similarity index 99%
rename from integratedauth/ntlm/ntlm_test.go
rename to ntlm_test.go
index 1df99e2..edac77a 100644
--- a/integratedauth/ntlm/ntlm_test.go
+++ b/ntlm_test.go
@@ -1,4 +1,6 @@
-package ntlm
+// +build !windows
+
+package mssql
 
 import (
 	"bytes"
diff --git a/queries_go19_amd64_test.go b/queries_go19_amd64_test.go
deleted file mode 100644
index 26be041..0000000
--- a/queries_go19_amd64_test.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package mssql
-
-import (
-	"fmt"
-	"testing"
-	"time"
-)
-
-func TestDateTimeParam19(t *testing.T) {
-	conn, logger := open(t)
-	defer conn.Close()
-	logger.StopLogging()
-
-	// testing DateTime1, only supported on go 1.9
-	var emptydate time.Time
-	mindate1 := time.Date(1753, 1, 1, 0, 0, 0, 0, time.UTC)
-	maxdate1 := time.Date(9999, 12, 31, 23, 59, 59, 997000000, time.UTC)
-	testdates1 := []DateTime1{
-		DateTime1(mindate1),
-		DateTime1(maxdate1),
-		DateTime1(time.Date(1752, 12, 31, 23, 59, 59, 997000000, time.UTC)), // just a little below minimum date
-		DateTime1(time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC)),             // just a little over maximum date
-		DateTime1(emptydate),
-	}
-
-	for _, test := range testdates1 {
-		t.Run(fmt.Sprintf("Test datetime for %v", test), func(t *testing.T) {
-			var res time.Time
-			expected := time.Time(test)
-			queryParamRoundTrip(conn, test, &res)
-			// clip value
-			if expected.Before(mindate1) {
-				expected = mindate1
-			}
-			if expected.After(maxdate1) {
-				expected = maxdate1
-			}
-			if expected.Sub(res) != 0 {
-				t.Errorf("expected: '%s', got: '%s' delta: %d", expected, res, expected.Sub(res))
-			}
-		})
-	}
-}
diff --git a/queries_go19_test.go b/queries_go19_test.go
index 6f462f0..c1fabeb 100644
--- a/queries_go19_test.go
+++ b/queries_go19_test.go
@@ -746,7 +746,6 @@ func TestParamNoName(t *testing.T) {
 //
 // Issue https://github.com/denisenkom/go-mssqldb/issues/166
 func TestTLSServerReadClose(t *testing.T) {
-	skipIfNamedPipesEnabled(t)
 	query := `
 with
     config_cte (config) as (
@@ -1013,6 +1012,42 @@ with
 	}
 }
 
+func TestDateTimeParam19(t *testing.T) {
+	conn, logger := open(t)
+	defer conn.Close()
+	logger.StopLogging()
+
+	// testing DateTime1, only supported on go 1.9
+	var emptydate time.Time
+	mindate1 := time.Date(1753, 1, 1, 0, 0, 0, 0, time.UTC)
+	maxdate1 := time.Date(9999, 12, 31, 23, 59, 59, 997000000, time.UTC)
+	testdates1 := []DateTime1{
+		DateTime1(mindate1),
+		DateTime1(maxdate1),
+		DateTime1(time.Date(1752, 12, 31, 23, 59, 59, 997000000, time.UTC)), // just a little below minimum date
+		DateTime1(time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC)),             // just a little over maximum date
+		DateTime1(emptydate),
+	}
+
+	for _, test := range testdates1 {
+		t.Run(fmt.Sprintf("Test datetime for %v", test), func(t *testing.T) {
+			var res time.Time
+			expected := time.Time(test)
+			queryParamRoundTrip(conn, test, &res)
+			// clip value
+			if expected.Before(mindate1) {
+				expected = mindate1
+			}
+			if expected.After(maxdate1) {
+				expected = maxdate1
+			}
+			if expected.Sub(res) != 0 {
+				t.Errorf("expected: '%s', got: '%s' delta: %d", expected, res, expected.Sub(res))
+			}
+		})
+	}
+}
+
 func TestReturnStatus(t *testing.T) {
 	conn, logger := open(t)
 	defer conn.Close()
@@ -1080,7 +1115,7 @@ func TestMessageQueue(t *testing.T) {
 	defer conn.Close()
 	defer logger.StopLogging()
 	retmsg := &sqlexp.ReturnMessage{}
-	latency := getLatency(t)
+	latency, _ := getLatency(t)
 	ctx, cancel := context.WithTimeout(context.Background(), latency+200000*time.Millisecond)
 	defer cancel()
 	rows, err := conn.QueryContext(ctx, "PRINT 'msg1'; select 100 as c; PRINT 'msg2'", retmsg)
@@ -1092,19 +1127,17 @@ func TestMessageQueue(t *testing.T) {
 
 	msgs := []interface{}{
 		sqlexp.MsgNotice{Message: Error{Message: "msg1"}},
-		sqlexp.MsgNextResultSet{},
 		sqlexp.MsgNext{},
 		sqlexp.MsgRowsAffected{Count: 1},
-		sqlexp.MsgNextResultSet{},
 		sqlexp.MsgNotice{Message: Error{Message: "msg2"}},
 		sqlexp.MsgNextResultSet{},
-		sqlexp.MsgNextResultSet{},
 	}
 	i := 0
+	rsCount := 0
 	for active {
 		msg := retmsg.Message(ctx)
 		if i >= len(msgs) {
-			t.Fatalf("Got extra message:%+v", reflect.TypeOf(msg))
+			t.Fatalf("Got extra message:%+v", msg)
 		}
 		t.Log(reflect.TypeOf(msg))
 		if reflect.TypeOf(msgs[i]) != reflect.TypeOf(msg) {
@@ -1115,6 +1148,10 @@ func TestMessageQueue(t *testing.T) {
 			t.Log(m.Message)
 		case sqlexp.MsgNextResultSet:
 			active = rows.NextResultSet()
+			if active {
+				t.Fatal("NextResultSet returned true")
+			}
+			rsCount++
 		case sqlexp.MsgNext:
 			if !rows.Next() {
 				t.Fatal("rows.Next() returned false")
@@ -1201,8 +1238,7 @@ select getdate()
 PRINT N'This is a message'
 select 199
 RAISERROR (N'Testing!' , 11, 1)
-declare @d int = 300
-select @d
+select 300
 `
 
 func testMixedQuery(conn *sql.DB, b testing.TB) (msgs, errs, results, rowcounts int) {
@@ -1262,7 +1298,7 @@ func TestTimeoutWithNoResults(t *testing.T) {
 	defer conn.Close()
 	defer logger.StopLogging()
 
-	latency := getLatency(t)
+	latency, _ := getLatency(t)
 	ctx, cancel := context.WithTimeout(context.Background(), latency+5000*time.Millisecond)
 	defer cancel()
 	retmsg := &sqlexp.ReturnMessage{}
@@ -1300,27 +1336,21 @@ func TestCancelWithNoResults(t *testing.T) {
 	defer conn.Close()
 	defer logger.StopLogging()
 
-	latency := getLatency(t)
-
-	ctx, cancel := context.WithTimeout(context.Background(), latency+15000*time.Millisecond)
+	latency, _ := getLatency(t)
+	ctx, cancel := context.WithTimeout(context.Background(), latency+5000*time.Millisecond)
 	retmsg := &sqlexp.ReturnMessage{}
-	t.Logf("Calling QueryContext")
 	r, err := conn.QueryContext(ctx, `waitfor delay '00:00:15'; select 100`, retmsg)
-	t.Logf("QueryContext returned")
 	if err != nil {
 		cancel()
 		t.Fatal(err.Error())
 	}
 	defer r.Close()
-	// QueryContext doesn't return until the connection is established
-	time.Sleep(100 * time.Millisecond)
-	t.Logf("Calling Cancel")
+	time.Sleep(latency + 100*time.Millisecond)
 	cancel()
-	t.Logf("Cancel returned")
 	active := true
 	for active {
 		msg := retmsg.Message(ctx)
-		t.Logf("%v Got a message: %s", time.Now(), reflect.TypeOf(msg))
+		t.Logf("Got a message: %s", reflect.TypeOf(msg))
 		switch m := msg.(type) {
 		case sqlexp.MsgNextResultSet:
 			active = r.NextResultSet()
@@ -1339,135 +1369,3 @@ func TestCancelWithNoResults(t *testing.T) {
 		t.Fatalf("Unexpected error: %v", r.Err())
 	}
 }
-
-const DropSprocWithCursor = `IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TestSqlCmd]') AND type in (N'P', N'PC'))
-DROP PROCEDURE [dbo].[TestSqlCmd]
-`
-
-// This query generates half a dozen tokenDoneInProc tokens which fill the channel if the app isn't scanning Rowsq
-const CreateSprocWithCursor = `
-CREATE PROCEDURE [dbo].[TestSqlCmd]
-AS
-BEGIN
-	DECLARE @tmp int;
-	DECLARE Server_Cursor CURSOR FOR
-	SELECT 1 UNION SELECT 2
-	OPEN Server_Cursor;
-	FETCH NEXT FROM Server_Cursor INTO @tmp;
-	WHILE @@FETCH_STATUS = 0
-		BEGIN
-		    PRINT @tmp
-			FETCH NEXT FROM Server_Cursor INTO @tmp;
-		END;
-	CLOSE Server_Cursor;
-	DEALLOCATE Server_Cursor;
-END
-`
-
-func TestSprocWithCursorNoResult(t *testing.T) {
-	conn, logger := open(t)
-	defer conn.Close()
-	defer logger.StopLogging()
-
-	_, e := conn.Exec(DropSprocWithCursor)
-	if e != nil {
-		t.Fatalf("Unable to drop test sproc: %v", e)
-	}
-	_, e = conn.Exec(CreateSprocWithCursor)
-	if e != nil {
-		t.Fatalf("Unable to create test sproc: %v", e)
-	}
-	defer conn.Exec(DropSprocWithCursor)
-	latency := getLatency(t)
-	ctx, cancel := context.WithTimeout(context.Background(), latency+500*time.Millisecond)
-	defer cancel()
-	retmsg := &sqlexp.ReturnMessage{}
-	// Use a sproc instead of the cursor loop directly to cover the different code path in token.go
-	r, err := conn.QueryContext(ctx, `exec [dbo].[TestSqlCmd]`, retmsg)
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-	defer r.Close()
-	active := true
-	rsCount := 0
-	msgCount := 0
-	for active {
-		msg := retmsg.Message(ctx)
-		t.Logf("Got a message: %v", reflect.TypeOf(msg))
-		switch m := msg.(type) {
-		case sqlexp.MsgNext:
-			t.Fatalf("Got a MsgNext from a query with no rows")
-		case sqlexp.MsgError:
-			t.Fatalf("Got an error: %s", m.Error.Error())
-		case sqlexp.MsgNotice:
-			msgCount++
-		case sqlexp.MsgNextResultSet:
-			if active = r.NextResultSet(); active {
-				rsCount++
-			}
-		}
-	}
-	if r.Err() != nil {
-		t.Fatalf("Got an error: %v", r.Err())
-	}
-	if rsCount != 13 {
-		t.Fatalf("Unexpected record set count: %v", rsCount)
-	}
-	if msgCount != 2 {
-		t.Fatalf("Unexpected message count: %v", msgCount)
-	}
-}
-
-func TestErrorAsLastResult(t *testing.T) {
-	conn, logger := open(t)
-	defer conn.Close()
-	defer logger.StopLogging()
-	latency := getLatency(t)
-	ctx, cancel := context.WithTimeout(context.Background(), latency+5000*time.Millisecond)
-	defer cancel()
-	retmsg := &sqlexp.ReturnMessage{}
-	// Use a sproc instead of the cursor loop directly to cover the different code path in token.go
-	r, err := conn.QueryContext(ctx,
-		`
-		Print N'message'
-		select 1
-		raiserror(N'Error!', 16, 1)`,
-		retmsg)
-	if err != nil {
-		t.Fatal(err.Error())
-	}
-	defer r.Close()
-	active := true
-	d := 0
-	err = nil
-	for active {
-		msg := retmsg.Message(ctx)
-		t.Logf("Got a message: %s", reflect.TypeOf(msg))
-		switch m := msg.(type) {
-		case sqlexp.MsgNext:
-			if !r.Next() {
-				t.Fatalf("Next returned false")
-			}
-			r.Scan(&d)
-			if r.Next() {
-				t.Fatal("Second Next returned true")
-			}
-		case sqlexp.MsgError:
-			err = m.Error
-		case sqlexp.MsgNextResultSet:
-			active = r.NextResultSet()
-		}
-	}
-	if err == nil {
-		t.Fatal("Should have gotten an error message")
-	} else {
-		switch e := err.(type) {
-		case Error:
-			if e.Message != "Error!" || e.Class != 16 {
-				t.Fatalf("Got the wrong mssql error %v", e)
-			}
-		default:
-			t.Fatalf("Got an unexpected error %v", e)
-		}
-	}
-}
diff --git a/queries_test.go b/queries_test.go
index e8ac23d..2b1125d 100644
--- a/queries_test.go
+++ b/queries_test.go
@@ -16,7 +16,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/microsoft/go-mssqldb/msdsn"
+	"github.com/denisenkom/go-mssqldb/msdsn"
 )
 
 func driverWithProcess(t *testing.T, tl Logger) *Driver {
@@ -488,10 +488,6 @@ func TestParams(t *testing.T) {
 	}
 	values := []interface{}{
 		int64(5),
-		int32(10),
-		int16(20),
-		int8(40),
-		int(10000),
 		"hello",
 		"",
 		[]byte{1, 2, 3},
@@ -529,19 +525,6 @@ func TestParams(t *testing.T) {
 				}
 			case time.Time:
 				same = decodedval.UTC() == val
-			case int64:
-				switch intVal := val.(type) {
-				case int16:
-					same = decodedval == int64(intVal)
-				case int32:
-					same = decodedval == int64(intVal)
-				case int8:
-					same = decodedval == int64(intVal)
-				case int:
-					same = decodedval == int64(intVal)
-				default:
-					same = retval == val
-				}
 			default:
 				same = retval == val
 			}
@@ -1499,7 +1482,7 @@ func TestLongConnection(t *testing.T) {
 		{"2", "00:00:01", 6 * time.Second, false},
 
 		// Check no connection timeout.
-		{"0", "00:00:01", 6 * time.Second, false},
+		{"0", "00:00:01", 2 * time.Second, false},
 		// {"0", "00:00:45", 60 * time.Second, false}, // Skip for normal testing to limit time.
 	}
 
@@ -1606,10 +1589,10 @@ func TestColumnTypeIntrospection(t *testing.T) {
 		{"cast('abc' as varbinary(max))", "VARBINARY", reflect.TypeOf([]byte{}), true, 2147483645, false, 0, 0},
 		{"cast(1 as datetime)", "DATETIME", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0},
 		{"cast(1 as smalldatetime)", "SMALLDATETIME", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0},
-		{"cast(getdate() as datetime2(7))", "DATETIME2", reflect.TypeOf(time.Time{}), false, 0, true, 0, 7},
-		{"cast(getdate() as datetimeoffset(7))", "DATETIMEOFFSET", reflect.TypeOf(time.Time{}), false, 0, true, 0, 7},
+		{"cast(getdate() as datetime2(7))", "DATETIME2", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0},
+		{"cast(getdate() as datetimeoffset(7))", "DATETIMEOFFSET", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0},
 		{"cast(getdate() as date)", "DATE", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0},
-		{"cast(getdate() as time)", "TIME", reflect.TypeOf(time.Time{}), false, 0, true, 0, 7},
+		{"cast(getdate() as time)", "TIME", reflect.TypeOf(time.Time{}), false, 0, false, 0, 0},
 		{"'abc'", "VARCHAR", reflect.TypeOf(""), true, 3, false, 0, 0},
 		{"cast('abc' as varchar(max))", "VARCHAR", reflect.TypeOf(""), true, 2147483645, false, 0, 0},
 		{"N'abc'", "NVARCHAR", reflect.TypeOf(""), true, 3, false, 0, 0},
@@ -1632,46 +1615,42 @@ func TestColumnTypeIntrospection(t *testing.T) {
 	defer conn.Close()
 	defer logger.StopLogging()
 	for _, tt := range tests {
-		t.Run(tt.expr, func(t *testing.T) {
-			rows, err := conn.Query("select " + tt.expr)
-			if err != nil {
-				t.Fatalf("Query failed with unexpected error %s", err)
-			}
-			// defer keyword is function scoped, so calling it inside a for loop within one function
-			// prevents the open connection from being reused in subsequent loop iterations
-			defer rows.Close()
-			ct, err := rows.ColumnTypes()
-			if err != nil {
-				t.Fatalf("Query failed with unexpected error %s", err)
-			}
-			if ct[0].DatabaseTypeName() != tt.typeName {
-				t.Errorf("Expected type %s but returned %s", tt.typeName, ct[0].DatabaseTypeName())
-			}
-			size, ok := ct[0].Length()
-			if ok != tt.hasSize {
-				t.Errorf("Expected has size %v but returned %v for %s", tt.hasSize, ok, tt.expr)
-			} else {
-				if ok && size != tt.size {
-					t.Errorf("Expected size %d but returned %d for %s", tt.size, size, tt.expr)
-				}
+		rows, err := conn.Query("select " + tt.expr)
+		if err != nil {
+			t.Fatalf("Query failed with unexpected error %s", err)
+		}
+		defer rows.Close()
+		ct, err := rows.ColumnTypes()
+		if err != nil {
+			t.Fatalf("Query failed with unexpected error %s", err)
+		}
+		if ct[0].DatabaseTypeName() != tt.typeName {
+			t.Errorf("Expected type %s but returned %s", tt.typeName, ct[0].DatabaseTypeName())
+		}
+		size, ok := ct[0].Length()
+		if ok != tt.hasSize {
+			t.Errorf("Expected has size %v but returned %v for %s", tt.hasSize, ok, tt.expr)
+		} else {
+			if ok && size != tt.size {
+				t.Errorf("Expected size %d but returned %d for %s", tt.size, size, tt.expr)
 			}
+		}
 
-			prec, scale, ok := ct[0].DecimalSize()
-			if ok != tt.hasPrecScale {
-				t.Errorf("Expected has prec/scale %v but returned %v for %s", tt.hasPrecScale, ok, tt.expr)
-			} else {
-				if ok && prec != tt.precision {
-					t.Errorf("Expected precision %d but returned %d for %s", tt.precision, prec, tt.expr)
-				}
-				if ok && scale != tt.scale {
-					t.Errorf("Expected scale %d but returned %d for %s", tt.scale, scale, tt.expr)
-				}
+		prec, scale, ok := ct[0].DecimalSize()
+		if ok != tt.hasPrecScale {
+			t.Errorf("Expected has prec/scale %v but returned %v for %s", tt.hasPrecScale, ok, tt.expr)
+		} else {
+			if ok && prec != tt.precision {
+				t.Errorf("Expected precision %d but returned %d for %s", tt.precision, prec, tt.expr)
 			}
-
-			if ct[0].ScanType() != tt.reflType {
-				t.Errorf("Expected ScanType %v but got %v for %s", tt.reflType, ct[0].ScanType(), tt.expr)
+			if ok && scale != tt.scale {
+				t.Errorf("Expected scale %d but returned %d for %s", tt.scale, scale, tt.expr)
 			}
-		})
+		}
+
+		if ct[0].ScanType() != tt.reflType {
+			t.Errorf("Expected ScanType %v but got %v for %s", tt.reflType, ct[0].ScanType(), tt.expr)
+		}
 	}
 }
 
@@ -2012,7 +1991,7 @@ func TestQueryCancelHighLevel(t *testing.T) {
 	defer logger.StopLogging()
 
 	ctx, cancel := context.WithCancel(context.Background())
-	latency := getLatency(t)
+	latency, _ := getLatency(t)
 
 	go func() {
 		time.Sleep(latency + 500*time.Millisecond)
@@ -2033,38 +2012,35 @@ func TestQueryCancelHighLevel(t *testing.T) {
 }
 
 // returns the minimum time needed to connect to the server
-func getLatency(t *testing.T) time.Duration {
-	t.Helper()
-	params, err := msdsn.Parse(makeConnStr(t).String())
-	if err != nil {
-		t.Fatalf("Invalid connection string: %s", err.Error())
-	}
-	c := &Connector{params: params}
-	now := time.Now()
-	if err := queryBrowser(context.Background(), context.Background(), c, nil, &params); err != nil {
-		t.Fatalf("queryBrowser failed: %s", err.Error())
-	}
-	// Dialing both tcp and np for a named-pipes only connection takes a long time
-	if len(params.Protocols) > 1 && testing.Short() {
-		t.Skip("short")
-	}
-	for _, protocol := range params.Protocols {
-		dialer := msdsn.ProtocolDialers[protocol]
-		sqlDialer, ok := dialer.(MssqlProtocolDialer)
-		if !ok {
-			conn, err := dialer.DialConnection(context.Background(), params)
-			if err == nil {
-				conn.Close()
-			}
-		} else {
-			conn, err := sqlDialer.DialSqlConnection(context.Background(), c, params)
-			if err == nil {
-				conn.Close()
+// Minimum return value is 1 ms, max is 2k ms
+func getLatency(t *testing.T) (latency time.Duration, increment time.Duration) {
+	latency = 1 * time.Millisecond
+	connstr := makeConnStr(t)
+	// .Host may not have a port
+	host := connstr.Hostname()
+	port := connstr.Port()
+	increment = 50 * time.Millisecond
+	if host == "." || host == "localhost" {
+		increment = 1 * time.Millisecond
+	}
+	if port == "" {
+		port = "1433"
+	}
+	for latency < 2000*time.Millisecond {
+		t.Logf("Dialing host %s with timeout %s", host, latency)
+		_, err := net.DialTimeout("tcp", host+":"+port, latency)
+		if err == nil {
+			return latency, increment
+		}
+		if oe, ok := err.(*net.OpError); ok {
+			if !oe.Timeout() {
+				t.Logf("Got non-timeout error %s", oe.Error())
+				return latency, increment
 			}
+			latency += increment
 		}
-
 	}
-	return time.Since(now)
+	return latency, increment
 }
 
 func TestQueryTimeout(t *testing.T) {
@@ -2072,7 +2048,7 @@ func TestQueryTimeout(t *testing.T) {
 	defer conn.Close()
 	defer logger.StopLogging()
 	// 2 seconds should be enough time to complete the login
-	latency := getLatency(t)
+	latency, _ := getLatency(t)
 	ctx, cancel := context.WithTimeout(context.Background(), latency+2000*time.Millisecond)
 	defer cancel()
 	_, err := conn.ExecContext(ctx, "waitfor delay '00:00:20'")
@@ -2096,9 +2072,9 @@ func TestLoginTimeout(t *testing.T) {
 	defer logger.StopLogging()
 	// Try to timeout during the login using a small delta from raw connect time
 	// In environments where latency is really low this degenerates into TestQueryTimeout
-	latency := getLatency(t)
+	latency, increment := getLatency(t)
 
-	ctx, cancel := context.WithTimeout(context.Background(), latency+200*time.Millisecond)
+	ctx, cancel := context.WithTimeout(context.Background(), latency+(2*increment))
 	defer cancel()
 	_, err := conn.ExecContext(ctx, "waitfor delay '00:00:03'")
 	t.Logf("Got error type %v: %s ", reflect.TypeOf(err), err.Error())
@@ -2106,8 +2082,7 @@ func TestLoginTimeout(t *testing.T) {
 		if !oe.Timeout() {
 			t.Fatalf("Got non-timeout error %s", oe.Error())
 		}
-		// The type of error is not guaranteed so just look for "timeout"
-	} else if err != context.DeadlineExceeded && !strings.Contains(err.Error(), "timeout") {
+	} else if err != context.DeadlineExceeded {
 		t.Fatalf("wrong kind of error for login or query timeout: %+v", err)
 	}
 
@@ -2295,8 +2270,6 @@ func TestDisconnect1(t *testing.T) {
 	if testing.Short() {
 		t.Skip("short")
 	}
-
-	skipIfNamedPipesEnabled(t)
 	checkConnStr(t)
 	tl := testLogger{t: t}
 	defer tl.StopLogging()
@@ -2353,7 +2326,6 @@ func TestDisconnect1(t *testing.T) {
 // TestDisconnect2 tests a read error so the query is started
 // but results cannot be read.
 func TestDisconnect2(t *testing.T) {
-	skipIfNamedPipesEnabled(t)
 	if testing.Short() {
 		t.Skip("short")
 	}
@@ -2361,7 +2333,7 @@ func TestDisconnect2(t *testing.T) {
 	tl := testLogger{t: t}
 	defer tl.StopLogging()
 	SetLogger(&tl)
-	latency := getLatency(t)
+	latency, _ := getLatency(t)
 
 	// Revert to the normal dialer after the test is done.
 	normalCreateDialer := createDialer
@@ -2430,7 +2402,6 @@ func TestDisconnect3(t *testing.T) {
 	if testing.Short() {
 		t.Skip("short")
 	}
-	skipIfNamedPipesEnabled(t)
 	checkConnStr(t)
 	tl := testLogger{t: t}
 	defer tl.StopLogging()
@@ -2716,10 +2687,3 @@ func TestTypeSizesFromQuery(t *testing.T) {
 		t.Errorf("VARBINARY(30) reported as (variable, length): (%v, %d)", ok, l)
 	}
 }
-
-func skipIfNamedPipesEnabled(t *testing.T) {
-	t.Helper()
-	if len(msdsn.ProtocolParsers) > 1 {
-		t.Skip("Skipping test due to named pipes dialer")
-	}
-}
diff --git a/tds_login_test.go b/tds_login_test.go
index ab5e00c..f7c4cb7 100644
--- a/tds_login_test.go
+++ b/tds_login_test.go
@@ -11,7 +11,7 @@ import (
 	"sync/atomic"
 	"testing"
 
-	"github.com/microsoft/go-mssqldb/msdsn"
+	"github.com/denisenkom/go-mssqldb/msdsn"
 )
 
 type MockTransportDialer struct {
@@ -119,7 +119,7 @@ func testLoginSequenceServer(result chan error, conn net.Conn, expectedPackets,
 }
 
 func TestLoginWithSQLServerAuth(t *testing.T) {
-	conn, err := NewConnector("sqlserver://test:secret@localhost:1433?Workstation ID=localhost&log=128&protocol=tcp")
+	conn, err := NewConnector("sqlserver://test:secret@localhost:1433?Workstation ID=localhost&log=128")
 	if err != nil {
 		t.Errorf("Unable to parse dummy DSN: %v", err)
 	}
@@ -170,7 +170,7 @@ func TestLoginWithSQLServerAuth(t *testing.T) {
 }
 
 func TestLoginWithSecurityTokenAuth(t *testing.T) {
-	config, err := msdsn.Parse("sqlserver://localhost:1433?Workstation ID=localhost&log=128&protocol=tcp")
+	config, _, err := msdsn.Parse("sqlserver://localhost:1433?Workstation ID=localhost&log=128")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -231,7 +231,7 @@ func TestLoginWithSecurityTokenAuth(t *testing.T) {
 }
 
 func TestLoginWithADALUsernamePasswordAuth(t *testing.T) {
-	config, err := msdsn.Parse("sqlserver://localhost:1433?Workstation ID=localhost&log=128&protocol=tcp")
+	config, _, err := msdsn.Parse("sqlserver://localhost:1433?Workstation ID=localhost&log=128")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -305,7 +305,7 @@ func TestLoginWithADALUsernamePasswordAuth(t *testing.T) {
 }
 
 func TestLoginWithADALManagedIdentityAuth(t *testing.T) {
-	config, err := msdsn.Parse("sqlserver://localhost:1433?Workstation ID=localhost&log=128&protocol=tcp")
+	config, _, err := msdsn.Parse("sqlserver://localhost:1433?Workstation ID=localhost&log=128")
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/tds_test.go b/tds_test.go
index e48ffbf..7d9af0d 100644
--- a/tds_test.go
+++ b/tds_test.go
@@ -13,13 +13,11 @@ import (
 	"os"
 	"path"
 	"runtime"
-	"strings"
 	"sync"
 	"testing"
 	"time"
-	"unicode/utf16"
 
-	"github.com/microsoft/go-mssqldb/msdsn"
+	"github.com/denisenkom/go-mssqldb/msdsn"
 )
 
 type MockTransport struct {
@@ -156,7 +154,7 @@ func TestSendLoginWithFeatureExt(t *testing.T) {
 
 func TestSendSqlBatch(t *testing.T) {
 	checkConnStr(t)
-	p, err := msdsn.Parse(makeConnStr(t).String())
+	p, _, err := msdsn.Parse(makeConnStr(t).String())
 	if err != nil {
 		t.Error("parseConnectParams failed:", err.Error())
 		return
@@ -225,7 +223,7 @@ func GetConnParams() (*msdsn.Config, error) {
 	dsn := os.Getenv("SQLSERVER_DSN")
 	const logFlags = 127
 	if len(dsn) > 0 {
-		params, err := msdsn.Parse(dsn)
+		params, _, err := msdsn.Parse(dsn)
 		if err != nil {
 			return nil, err
 		}
@@ -233,22 +231,14 @@ func GetConnParams() (*msdsn.Config, error) {
 		return &params, nil
 	}
 	if len(os.Getenv("HOST")) > 0 && len(os.Getenv("DATABASE")) > 0 {
-		c := &msdsn.Config{
-			Host:       os.Getenv("HOST"),
-			Instance:   os.Getenv("INSTANCE"),
-			Database:   os.Getenv("DATABASE"),
-			User:       os.Getenv("SQLUSER"),
-			Password:   os.Getenv("SQLPASSWORD"),
-			LogFlags:   logFlags,
-			Parameters: make(map[string]string),
-		}
-		if c.Instance == "" {
-			c.Instance = os.Getenv("SQLINSTANCE")
-		}
-		if os.Getenv("PROTOCOL") != "" {
-			c.Parameters["protocol"] = os.Getenv("PROTOCOL")
-		}
-		return c, nil
+		return &msdsn.Config{
+			Host:     os.Getenv("HOST"),
+			Instance: os.Getenv("INSTANCE"),
+			Database: os.Getenv("DATABASE"),
+			User:     os.Getenv("SQLUSER"),
+			Password: os.Getenv("SQLPASSWORD"),
+			LogFlags: logFlags,
+		}, nil
 	}
 	// try loading connection string from file
 	f, err := os.Open(".connstr")
@@ -258,7 +248,7 @@ func GetConnParams() (*msdsn.Config, error) {
 		if err != io.EOF && err != nil {
 			return nil, err
 		}
-		params, err := msdsn.Parse(dsn)
+		params, _, err := msdsn.Parse(dsn)
 		if err != nil {
 			return nil, err
 		}
@@ -366,7 +356,6 @@ func TestConnectViaIp(t *testing.T) {
 	if params.Encryption == msdsn.EncryptionRequired {
 		t.Skip("Unable to test connection to IP for servers that expect encryption")
 	}
-	skipIfNamedPipesEnabled(t)
 
 	if params.Host == "." {
 		params.Host = "127.0.0.1"
@@ -585,43 +574,14 @@ func TestBadCredentials(t *testing.T) {
 	params := testConnParams(t)
 	params.Password = "padpwd"
 	params.User = "baduser"
-	_ = testConnectionBad(t, params.URL().String())
+	testConnectionBad(t, params.URL().String())
 }
 
 func TestBadHost(t *testing.T) {
 	params := testConnParams(t)
 	params.Host = "badhost"
 	params.Instance = ""
-	_ = testConnectionBad(t, params.URL().String())
-}
-
-func TestSqlBrowserNotUsedIfPortSpecified(t *testing.T) {
-	const errorSubstrStringToCheckFor = "unable to get instances from Sql Server Browser"
-
-	// Connect to an instance on a host that doesn't exist (so connection will always expectedly fail)
-	params := testConnParams(t)
-	params.Host = "badhost"
-	params.Instance = "foobar"
-	protocols := params.Protocols
-	params.Protocols = []string{"tcp"}
-
-	// Specify no port, so error must indicate SQL Browser lookup failed
-	params.Port = 0 // No port spcified, sql browser should be used
-
-	err := testConnectionBad(t, params.URL().String())
-
-	if !strings.Contains(err.Error(), errorSubstrStringToCheckFor) {
-		t.Fatal("Connection should have tried to use SQL Browser")
-	}
-
-	// Specify port, ensure error does not indicate SQL Browser lookup failed
-	params.Port = 1500 // Specify a port, sql browser should not be tried
-	params.Protocols = protocols
-	err = testConnectionBad(t, params.URL().String())
-
-	if strings.Contains(err.Error(), errorSubstrStringToCheckFor) {
-		t.Fatal("Connection should not have tried to use SQL Browser, because none zero Port specified")
-	}
+	testConnectionBad(t, params.URL().String())
 }
 
 func TestSSPIAuth(t *testing.T) {
@@ -670,160 +630,6 @@ func TestUcs22Str(t *testing.T) {
 	}
 }
 
-var encoded123456789Bytes = []byte{0x31, 0, 0x32, 0, 0x33, 0, 0x34, 0, 0x35, 0, 0x36, 0, 0x37, 0, 0x38, 0, 0x39, 0}
-var encoded12345678Bytes = []byte{0x31, 0, 0x32, 0, 0x33, 0, 0x34, 0, 0x35, 0, 0x36, 0, 0x37, 0, 0x38, 0}
-var encoded1234567Bytes = []byte{0x31, 0, 0x32, 0, 0x33, 0, 0x34, 0, 0x35, 0, 0x36, 0, 0x37, 0}
-var encoded123456Bytes = []byte{0x31, 0, 0x32, 0, 0x33, 0, 0x34, 0, 0x35, 0, 0x36, 0}
-var encoded12345Bytes = []byte{0x31, 0, 0x32, 0, 0x33, 0, 0x34, 0, 0x35, 0}
-var encoded1234Bytes = []byte{0x31, 0, 0x32, 0, 0x33, 0, 0x34, 0}
-var encoded123Bytes = []byte{0x31, 0, 0x32, 0, 0x33, 0}
-var encoded12Bytes = []byte{0x31, 0, 0x32, 0}
-var encoded1Bytes = []byte{0x31, 0}
-
-var encodedLongASCIIBytes = []byte{0x31, 0, 0x32, 0, 0x33, 0, 0x34, 0, 0x35, 0, 0x36, 0, 0x37, 0, 0x38, 0, 0x39, 0,
-	// a-z
-	0x61, 0x0, 0x62, 0x0, 0x63, 0x0, 0x64, 0x0, 0x65, 0x0, 0x66, 0x0, 0x67, 0x0, 0x68, 0x0, 0x69, 0x0, 0x6a, 0x0, 0x6b, 0x0, 0x6c, 0x0, 0x6d, 0x0, 0x6e, 0x0, 0x6f, 0x0, 0x70, 0x0, 0x71, 0x0, 0x72, 0x0, 0x73, 0x0, 0x74, 0x0, 0x75, 0x0, 0x76, 0x0, 0x77, 0x0, 0x78, 0x0, 0x79, 0x0, 0x7a, 0x0,
-	// A-Z
-	0x41, 0x0, 0x42, 0x0, 0x43, 0x0, 0x44, 0x0, 0x45, 0x0, 0x46, 0x0, 0x47, 0x0, 0x48, 0x0, 0x49, 0x0, 0x4a, 0x0, 0x4b, 0x0, 0x4c, 0x0, 0x4d, 0x0, 0x4e, 0x0, 0x4f, 0x0, 0x50, 0x0, 0x51, 0x0, 0x52, 0x0, 0x53, 0x0, 0x54, 0x0, 0x55, 0x0, 0x56, 0x0, 0x57, 0x0, 0x58, 0x0, 0x59, 0x0, 0x5a, 0x0,
-}
-var decodedLongASCIIString string = "123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
-// multiple copies of the above
-var encodedLongerASCIIBytes []byte
-var decodedLongerASCIIString string
-
-var encodedUnicode1 = []byte{0x61, 0x0, 0x62, 0x0, 0x63, 0x0, 0x64, 0x0, 0x65, 0x0, 0x66, 0x0, 0x67, 0x0, 0x68, 0x0, 0x69, 0x0, 0x6a, 0x1}
-var encodedUnicode2 = []byte{0x61, 0x0, 0x62, 0x0, 0x63, 0x0, 0x64, 0x0, 0x65, 0x0, 0x66, 0x0, 0x67, 0x0, 0x68, 0x0, 0x69, 0x0, 0x6a, 0x0, 0x6b, 0x0, 0x6c, 0x0, 0x6d, 0x1}
-var encodedUnicode3 = []byte{0x61, 0x0, 0x62, 0x0, 0x63, 0x0, 0x64, 0x0, 0x65, 0x0, 0x66, 0x0, 0x67, 0x0, 0x68, 0x0, 0x69, 0x0, 0x6a, 0x0, 0x6b, 0x0, 0x6c, 0x0, 0x6d, 0x1, 0x1, 0x1}
-var encodedASCIIWithTrailingUnicode = []byte{0x61, 0x0, 0x62, 0x0, 0x63, 0x0, 0x64, 0x0, 0x65, 0x0, 0x66, 0x0, 0x67, 0x0, 0x68, 0x0, 0x69, 0x0, 0x6a, 0x0, 0x6b, 0x0, 0x6c, 0x0, 0x6d, 0x0, 0x6e, 0x0, 0x6f, 0x0, 0x7e, 0x76, 0x70, 0x0}
-var stringASCIIWithTrailingUnicode = "abcdefghijklmno百p"
-var longEmoji = "😀😃😄😁😆😅🤣😂🙂🙃😉😊😇😍🤩😘😗"
-var longEmojiBytes []byte
-var encodedASCIIWithTrailingUnicode2 []byte
-
-// create various test strings and byte slices for the ucs22str function
-func init() {
-
-	uint16s := utf16.Encode([]rune(longEmoji))
-
-	longEmojiBytes = make([]byte, len(uint16s)*2)
-
-	for i := 0; i < len(uint16s); i++ {
-		longEmojiBytes[i*2] = byte(uint16s[i] & 0xFF)
-		longEmojiBytes[(i*2)+1] = byte((uint16s[i] >> 8) & 0xFF)
-	}
-
-	uint16s = utf16.Encode([]rune(stringASCIIWithTrailingUnicode))
-
-	encodedASCIIWithTrailingUnicode2 = make([]byte, len(uint16s)*2)
-
-	for i := 0; i < len(uint16s); i++ {
-		encodedASCIIWithTrailingUnicode2[i*2] = byte(uint16s[i] & 0xFF)
-		encodedASCIIWithTrailingUnicode2[(i*2)+1] = byte((uint16s[i] >> 8) & 0xFF)
-	}
-
-	equal := bytes.Compare(encodedASCIIWithTrailingUnicode, encodedASCIIWithTrailingUnicode2)
-
-	if equal != 0 {
-		fmt.Print("Expected array to equal.")
-	}
-
-	for i := 0; i < 10; i++ {
-		encodedLongerASCIIBytes = append(encodedLongerASCIIBytes, encodedLongASCIIBytes...)
-		decodedLongerASCIIString = decodedLongerASCIIString + decodedLongASCIIString
-	}
-}
-
-func ExerciseUCS2ToStringFunction(name string, sut func([]byte) (string, error), t *testing.T) {
-
-	tests := []struct {
-		name     string
-		input    []byte
-		expected string
-	}{
-		{"Ascii 1", encoded1Bytes, "1"},
-		{"Ascii 2", encoded12Bytes, "12"},
-		{"Ascii 3", encoded123Bytes, "123"},
-		{"Ascii 4", encoded1234Bytes, "1234"},
-		{"Ascii 5", encoded12345Bytes, "12345"},
-		{"Ascii 6", encoded123456Bytes, "123456"},
-		{"Ascii 7", encoded1234567Bytes, "1234567"},
-		{"Ascii 8", encoded12345678Bytes, "12345678"},
-		{"Ascii 9", encoded123456789Bytes, "123456789"},
-		{"Long Ascii", encodedLongASCIIBytes, decodedLongASCIIString},
-		{"Longer Ascii", encodedLongerASCIIBytes, decodedLongerASCIIString},
-		{"Random Unicode1", encodedUnicode1, "abcdefghiŪ"},
-		{"Random Unicode2", encodedUnicode2, "abcdefghijklŭ"},
-		{"Random Unicode3", encodedUnicode3, "abcdefghijklŭā"},
-		{"TrailingUnicode", encodedASCIIWithTrailingUnicode, stringASCIIWithTrailingUnicode},
-		{"LongEmoji", longEmojiBytes, longEmoji},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-
-			actual, err := sut(tt.input)
-
-			if err != nil {
-				t.Errorf("%s errored: %s", name, err)
-			}
-
-			if actual != tt.expected {
-				t.Errorf("%s expected to return %s but it returned %s", name, tt.expected, actual)
-			}
-		})
-	}
-}
-
-func TestUcs22str(t *testing.T) {
-	ExerciseUCS2ToStringFunction("ucs22str", ucs22str, t)
-}
-
-var sideeffect_varchar string
-
-//ucs22str benchmarks
-func BenchmarkUcs22strAscii(b *testing.B) {
-	for n := 0; n < b.N; n++ {
-		s, _ := ucs22str(encoded123Bytes)
-		sideeffect_varchar = s
-	}
-}
-
-func BenchmarkUcs22strMediumAscii(b *testing.B) {
-	for n := 0; n < b.N; n++ {
-		s, _ := ucs22str(encoded123456789Bytes)
-		sideeffect_varchar = s
-	}
-}
-
-func BenchmarkUcs22strLongAscii(b *testing.B) {
-	for n := 0; n < b.N; n++ {
-		s, _ := ucs22str(encodedLongASCIIBytes)
-		sideeffect_varchar = s
-	}
-}
-
-func BenchmarkUcs22strLongerAscii(b *testing.B) {
-	for n := 0; n < b.N; n++ {
-		s, _ := ucs22str(encodedLongerASCIIBytes)
-		sideeffect_varchar = s
-	}
-}
-
-func BenchmarkUcs22strTrailingUnicode(b *testing.B) {
-	for n := 0; n < b.N; n++ {
-		s, _ := ucs22str(encodedASCIIWithTrailingUnicode)
-		sideeffect_varchar = s
-	}
-}
-
-func BenchmarkUcs22strLongEmojis(b *testing.B) {
-	for n := 0; n < b.N; n++ {
-		s, _ := ucs22str(longEmojiBytes)
-		sideeffect_varchar = s
-	}
-}
-
 func TestReadUcs2(t *testing.T) {
 	buf := bytes.NewBuffer([]byte{0x31, 0, 0x32, 0, 0x33, 0}) // 123 in UCS2 encoding
 	s, err := readUcs2(buf, 3)
@@ -887,7 +693,7 @@ func TestReadBVarByte(t *testing.T) {
 
 func BenchmarkPacketSize(b *testing.B) {
 	checkConnStr(b)
-	p, err := msdsn.Parse(makeConnStr(b).String())
+	p, _, err := msdsn.Parse(makeConnStr(b).String())
 	if err != nil {
 		b.Error("parseConnectParams failed:", err.Error())
 		return
diff --git a/tvp_example_test.go b/tvp_example_test.go
index 2f8ede5..c27f98e 100644
--- a/tvp_example_test.go
+++ b/tvp_example_test.go
@@ -8,7 +8,7 @@ import (
 	"fmt"
 	"log"
 
-	mssql "github.com/microsoft/go-mssqldb"
+	mssql "github.com/denisenkom/go-mssqldb"
 )
 
 // This example shows how to use tvp type
diff --git a/tvp_go19_db_test.go b/tvp_go19_db_test.go
index a862698..da80c19 100644
--- a/tvp_go19_db_test.go
+++ b/tvp_go19_db_test.go
@@ -1348,3 +1348,129 @@ func TestTVPUnsigned(t *testing.T) {
 		t.Errorf("third result set had wrong value expected: %s actual: %s", "test", result3)
 	}
 }
+
+func TestTVPIdentity(t *testing.T) {
+	type TvpIdentityExample struct {
+		ID      int `tvp:"@identity"`
+		Message string
+	}
+
+	const (
+		crateSchema = `create schema TestTVPSchemaIdentity;`
+
+		dropSchema = `drop schema TestTVPSchemaIdentity;`
+
+		createTVP = `
+		CREATE TYPE TestTVPSchemaIdentity.exempleTVP AS TABLE
+		(
+		    id int  identity(1,1) not null,
+			message	NVARCHAR(100)
+		)`
+
+		dropTVP = `DROP TYPE TestTVPSchemaIdentity.exempleTVP;`
+
+		procedureWithTVP = `	
+	CREATE PROCEDURE ExecIdentityTVP
+		@param1 TestTVPSchemaIdentity.exempleTVP READONLY
+	AS   
+	BEGIN
+		SET NOCOUNT ON; 
+		SELECT * FROM @param1;
+	END;
+	`
+
+		dropProcedure = `drop PROCEDURE ExecIdentityTVP`
+
+		execTvp = `exec ExecIdentityTVP @param1;`
+	)
+
+	checkConnStr(t)
+	tl := testLogger{t: t}
+	defer tl.StopLogging()
+	SetLogger(&tl)
+
+	p := makeConnStr(t).String()
+	conn, err := sql.Open("sqlserver", p)
+	if err != nil {
+		log.Fatal("Open connection failed:", err.Error())
+	}
+	defer conn.Close()
+
+	_, err = conn.Exec(crateSchema)
+	if err != nil {
+		t.Fatal(err)
+		return
+	}
+	defer conn.Exec(dropSchema)
+
+	_, err = conn.Exec(createTVP)
+	if err != nil {
+		t.Fatal(err)
+		return
+	}
+	defer conn.Exec(dropTVP)
+
+	_, err = conn.Exec(procedureWithTVP)
+	if err != nil {
+		t.Fatal(err)
+		return
+	}
+	defer conn.Exec(dropProcedure)
+
+	exempleData := []TvpIdentityExample{
+		{
+			Message: "Hello",
+		},
+		{
+			Message: "World",
+		},
+		{
+			Message: "TVP",
+		},
+	}
+
+	tvpType := TVP{
+		TypeName: "TestTVPSchemaIdentity.exempleTVP",
+		Value:    exempleData,
+	}
+
+	rows, err := conn.Query(execTvp,
+		sql.Named("param1", tvpType),
+	)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer rows.Close()
+
+	tvpResult := make([]TvpIdentityExample, 0)
+	for rows.Next() {
+		tvpExemple := TvpIdentityExample{}
+		err = rows.Scan(&tvpExemple.ID, &tvpExemple.Message)
+		if err != nil {
+			t.Fatal(err)
+		}
+		tvpResult = append(tvpResult, tvpExemple)
+	}
+
+	expectData := []TvpIdentityExample{
+		{
+			ID:      1,
+			Message: "Hello",
+		},
+		{
+			ID:      2,
+			Message: "World",
+		},
+		{
+			ID:      3,
+			Message: "TVP",
+		},
+	}
+
+	if len(expectData) != len(tvpResult) {
+		t.Fatal("TestTVPIdentity have to be len")
+	}
+	if !reflect.DeepEqual(expectData, tvpResult) {
+		t.Fatal("TestTVPIdentity have to be same")
+	}
+}