Skip to content

Commit 8ea6742

Browse files
committed
Add plumbing to get a connection's instance name.
1 parent 4f73e43 commit 8ea6742

File tree

11 files changed

+125
-39
lines changed

11 files changed

+125
-39
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,9 @@
10311031
<Compile Include="$(CommonSourceRoot)Resources\StringsHelper.cs">
10321032
<Link>Resources\StringsHelper.cs</Link>
10331033
</Compile>
1034+
<Compile Include="$(CommonSourceRoot)System\Text\EncodingExtensions.cs">
1035+
<Link>System\Text\EncodingExtensions.cs</Link>
1036+
</Compile>
10341037
<Compile Include="$(CommonSourceRoot)TypeForwards.netcore.cs">
10351038
<Link>TypeForwards.netcore.cs</Link>
10361039
</Compile>

src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,9 @@
10201020
<Compile Include="$(CommonSourceRoot)System\IO\StreamExtensions.netfx.cs">
10211021
<Link>System\IO\StreamExtensions.netfx.cs</Link>
10221022
</Compile>
1023+
<Compile Include="$(CommonSourceRoot)System\Text\EncodingExtensions.cs">
1024+
<Link>System\Text\EncodingExtensions.cs</Link>
1025+
</Compile>
10231026
<Compile Include="$(CommonSourceRoot)System\Runtime\CompilerServices\IsExternalInit.netfx.cs">
10241027
<Link>System\Runtime\CompilerServices\IsExternalInit.netfx.cs</Link>
10251028
</Compile>

src/Microsoft.Data.SqlClient/src/Interop/Windows/Sni/SniNativeWrapper.cs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ internal static unsafe uint SniOpenSyncEx(
171171
string connString,
172172
ref IntPtr pConn,
173173
ref string spn,
174-
byte[] instanceName,
174+
ref string instanceName,
175175
bool fOverrideCache,
176176
bool fSync,
177177
int timeout,
@@ -186,9 +186,13 @@ internal static unsafe uint SniOpenSyncEx(
186186
SQLDNSInfo cachedDnsInfo,
187187
string hostNameInCertificate)
188188
{
189-
fixed (byte* pInstanceName = instanceName)
189+
// Size of this buffer is as specified by netlibs.
190+
ReadOnlySpan<byte> instanceNameBuffer = stackalloc byte[256];
191+
192+
fixed (byte* pInstanceName = instanceNameBuffer)
190193
{
191194
SniClientConsumerInfo clientConsumerInfo = new SniClientConsumerInfo();
195+
uint result;
192196

193197
// initialize client ConsumerInfo part first
194198
MarshalConsumerInfo(consumerInfo, ref clientConsumerInfo.ConsumerInfo);
@@ -197,7 +201,7 @@ internal static unsafe uint SniOpenSyncEx(
197201
clientConsumerInfo.HostNameInCertificate = hostNameInCertificate;
198202
clientConsumerInfo.networkLibrary = Prefix.UNKNOWN_PREFIX;
199203
clientConsumerInfo.szInstanceName = pInstanceName;
200-
clientConsumerInfo.cchInstanceName = (uint)instanceName.Length;
204+
clientConsumerInfo.cchInstanceName = (uint)instanceNameBuffer.Length;
201205
clientConsumerInfo.fOverrideLastConnectCache = fOverrideCache;
202206
clientConsumerInfo.fSynchronousConnection = fSync;
203207
clientConsumerInfo.timeout = timeout;
@@ -236,22 +240,21 @@ internal static unsafe uint SniOpenSyncEx(
236240
{
237241
// An empty string implies we need to find the SPN so we supply a buffer for the max size
238242
var array = ArrayPool<byte>.Shared.Rent(SniMaxComposedSpnLength);
239-
array.AsSpan().Clear();
243+
Span<byte> arraySpan = array.AsSpan();
240244

245+
arraySpan.Clear();
241246
try
242247
{
243-
fixed (byte* pin_spnBuffer = array)
248+
fixed (byte* pin_spnBuffer = arraySpan)
244249
{
245250
clientConsumerInfo.szSPN = pin_spnBuffer;
246251
clientConsumerInfo.cchSPN = (uint)SniMaxComposedSpnLength;
247252

248-
var result = s_nativeMethods.SniOpenSyncExWrapper(ref clientConsumerInfo, out pConn);
249-
if (result == 0)
253+
result = s_nativeMethods.SniOpenSyncExWrapper(ref clientConsumerInfo, out pConn);
254+
if (result is TdsEnums.SNI_SUCCESS)
250255
{
251-
spn = Encoding.Unicode.GetString(array).TrimEnd('\0');
256+
spn = Encoding.Unicode.CreateStringFromNullTerminated(arraySpan);
252257
}
253-
254-
return result;
255258
}
256259
}
257260
finally
@@ -275,7 +278,7 @@ internal static unsafe uint SniOpenSyncEx(
275278
{
276279
clientConsumerInfo.szSPN = pin_spnBuffer;
277280
clientConsumerInfo.cchSPN = (uint)writer.WrittenCount;
278-
return s_nativeMethods.SniOpenSyncExWrapper(ref clientConsumerInfo, out pConn);
281+
result = s_nativeMethods.SniOpenSyncExWrapper(ref clientConsumerInfo, out pConn);
279282
}
280283
}
281284
finally
@@ -284,9 +287,18 @@ internal static unsafe uint SniOpenSyncEx(
284287
}
285288
}
286289
}
290+
else
291+
{
292+
// Otherwise leave szSPN null (SQL Auth)
293+
result = s_nativeMethods.SniOpenSyncExWrapper(ref clientConsumerInfo, out pConn);
294+
}
295+
296+
if (result is TdsEnums.SNI_SUCCESS)
297+
{
298+
instanceName = Encoding.UTF8.CreateStringFromNullTerminated(instanceNameBuffer);
299+
}
287300

288-
// Otherwise leave szSPN null (SQL Auth)
289-
return s_nativeMethods.SniOpenSyncExWrapper(ref clientConsumerInfo, out pConn);
301+
return result;
290302
}
291303
}
292304

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Connection/SqlConnectionInternal.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,8 @@ internal bool IgnoreEnvChange
601601

602602
internal string UserInstanceName { get; private set; } = string.Empty;
603603

604+
internal string InstanceName { get; set; }
605+
604606
internal bool Is2008OrNewer
605607
{
606608
get => _parser.Is2008OrNewer;

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ManagedSni/SniProxy.netcore.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ internal class SniProxy
4949
internal static SniHandle CreateConnectionHandle(
5050
string fullServerName,
5151
TimeoutTimer timeout,
52-
out byte[] instanceName,
52+
out string instanceName,
5353
out ResolvedServerSpn resolvedSpn,
5454
string serverSPN,
5555
bool flushCache,
@@ -63,7 +63,7 @@ internal static SniHandle CreateConnectionHandle(
6363
string hostNameInCertificate,
6464
string serverCertificateFilename)
6565
{
66-
instanceName = new byte[1];
66+
instanceName = null;
6767
resolvedSpn = default;
6868

6969
bool errorWithLocalDBProcessing;
@@ -99,6 +99,8 @@ internal static SniHandle CreateConnectionHandle(
9999
break;
100100
}
101101

102+
instanceName = details.InstanceName;
103+
102104
if (isIntegratedSecurity)
103105
{
104106
try

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParser.cs

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ bool withFailover
449449
trustServerCert = false;
450450
}
451451

452-
byte[] instanceName = null;
452+
string instanceName = null;
453453

454454
Debug.Assert(_connHandler != null, "SqlConnectionInternalTds handler can not be null at this point.");
455455
_connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin);
@@ -490,6 +490,7 @@ bool withFailover
490490
}
491491

492492
_connHandler.pendingSQLDNSObject = null;
493+
_connHandler.InstanceName = null;
493494

494495
// AD Integrated behaves like Windows integrated when connecting to a non-fedAuth server
495496
_physicalStateObj.CreatePhysicalSNIHandle(
@@ -569,7 +570,7 @@ bool withFailover
569570

570571
// UNDONE - send "" for instance now, need to fix later
571572
SqlClientEventSource.Log.TryTraceEvent("<sc.TdsParser.Connect|SEC> Sending prelogin handshake");
572-
SendPreLoginHandshake(instanceName, encrypt, integratedSecurity, serverCertificateFilename);
573+
SendPreLoginHandshake(encrypt, integratedSecurity, serverCertificateFilename);
573574

574575
_connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake);
575576
_connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake);
@@ -629,7 +630,7 @@ bool withFailover
629630
_physicalStateObj.AssignPendingDNSInfo(serverInfo.UserProtocol, FQDNforDNSCache, ref _connHandler.pendingSQLDNSObject);
630631
}
631632

632-
SendPreLoginHandshake(instanceName, encrypt, integratedSecurity, serverCertificateFilename);
633+
SendPreLoginHandshake(encrypt, integratedSecurity, serverCertificateFilename);
633634
status = ConsumePreLoginHandshake(
634635
encrypt,
635636
trustServerCert,
@@ -649,6 +650,7 @@ bool withFailover
649650
}
650651
SqlClientEventSource.Log.TryTraceEvent("<sc.TdsParser.Connect|SEC> Prelogin handshake successful");
651652

653+
_connHandler.InstanceName = instanceName;
652654
if (_authenticationProvider is { })
653655
{
654656
_authenticationProvider.Initialize(serverInfo, _physicalStateObj, this, resolvedServerSpn.Primary, resolvedServerSpn.Secondary);
@@ -773,7 +775,6 @@ internal void PutSession(TdsParserStateObject session)
773775
}
774776

775777
private void SendPreLoginHandshake(
776-
byte[] instanceName,
777778
SqlConnectionEncryptOption encrypt,
778779
bool integratedSecurity,
779780
string serverCertificateFilename)
@@ -868,21 +869,12 @@ private void SendPreLoginHandshake(
868869
break;
869870

870871
case (int)PreLoginOptions.INSTANCE:
871-
int i = 0;
872+
// Always send an empty null-terminated string
873+
payload[payloadLength] = 0;
872874

873-
while (instanceName[i] != 0)
874-
{
875-
payload[payloadLength] = instanceName[i];
876-
payloadLength++;
877-
i++;
878-
}
879-
880-
payload[payloadLength] = 0; // null terminate
881875
payloadLength++;
882-
i++;
883-
884-
offset += i;
885-
optionDataSize = i;
876+
offset += 1;
877+
optionDataSize = 1;
886878
break;
887879

888880
case (int)PreLoginOptions.THREADID:

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserSafeHandles.windows.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ internal SNIHandle(
146146
string serverName,
147147
ref string spn,
148148
int timeout,
149-
out byte[] instanceName,
149+
out string instanceName,
150150
bool flushCache,
151151
bool fSync,
152152
bool fParallel,
@@ -160,7 +160,7 @@ internal SNIHandle(
160160
: base(IntPtr.Zero, true)
161161
{
162162
_fSync = fSync;
163-
instanceName = new byte[256]; // Size as specified by netlibs.
163+
instanceName = null;
164164
// Option ignoreSniOpenTimeout is no longer available
165165
//if (ignoreSniOpenTimeout)
166166
//{
@@ -177,7 +177,7 @@ internal SNIHandle(
177177
serverName,
178178
ref base.handle,
179179
ref spn,
180-
instanceName,
180+
ref instanceName,
181181
flushCache,
182182
fSync,
183183
timeout,
@@ -193,7 +193,7 @@ internal SNIHandle(
193193
serverName,
194194
ref base.handle,
195195
ref spn,
196-
instanceName,
196+
ref instanceName,
197197
flushCache,
198198
fSync,
199199
timeout,

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ internal long TimeoutTime
556556
internal abstract void CreatePhysicalSNIHandle(
557557
string serverName,
558558
TimeoutTimer timeout,
559-
out byte[] instanceName,
559+
out string instanceName,
560560
out ResolvedServerSpn resolvedSpn,
561561
bool flushCache,
562562
bool async,

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObjectManaged.netcore.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ protected override uint SniPacketGetData(PacketHandle packet, byte[] inBuff, ref
8282
internal override void CreatePhysicalSNIHandle(
8383
string serverName,
8484
TimeoutTimer timeout,
85-
out byte[] instanceName,
85+
out string instanceName,
8686
out ResolvedServerSpn resolvedSpn,
8787
bool flushCache,
8888
bool async,

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObjectNative.windows.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ private ConsumerInfo CreateConsumerInfo(bool async)
139139
internal override void CreatePhysicalSNIHandle(
140140
string serverName,
141141
TimeoutTimer timeout,
142-
out byte[] instanceName,
142+
out string instanceName,
143143
out ManagedSni.ResolvedServerSpn resolvedSpn,
144144
bool flushCache,
145145
bool async,

0 commit comments

Comments
 (0)