Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu konuda, Windows hata ayıklayıcısı için özel bir kimlik bilgisi sağlayıcısının nasıl programlandığı açıklanmaktadır. Bu, benzersiz kimlik doğrulama türleri gerektiren ek sembol ve kaynak sunucuların kullanılmasına olanak tanır. Özelleştirme, sunucunun gerektirebileceği herhangi bir kimlik doğrulaması türünün kullanılmasına izin verir.
İki seçenek vardır:
- Yürütülebilir dosya aracılığıyla uygulanan (veya CMD/BAT betiğiyle başlatılan) özel sağlayıcı.
- Özel sağlayıcı, bu belgede açıklanan API arayüzü kullanılarak bir DLL olarak uygulanmıştır.
Windows hata ayıklayıcısı HTTPS kimlik doğrulama istekleri
Windows hata ayıklayıcıları bir sembol sunucusundan semboller ister ve sembol sunucusu kimlik doğrulaması gerektirmezse, semboller herhangi bir kimlik bilgisi sağlayıcısı kullanılmadan döndürülür. Sembol sunucusu HTTP_STATUS_DENIED 401 (Yetkisiz Erişim / Erişim Reddedildi) durum kodunu döndürürse, bu hata ayıklayıcıya kimlik doğrulaması gerektiğini gösterir. 401 yetkisiz kodu, isteğin hedef kaynak için geçerli kimlik doğrulaması kimlik bilgilerine sahip olmadığını gösterir. Bu, istemci gerekli kimlik doğrulama bilgilerini sağlamadığından sunucunun isteği gerçekleştirmeyi reddettiği anlamına gelir.
Özel bir kimlik bilgisi sağlayıcısı yapılandırılırsa, bu sağlayıcı kullanılacak ve döndürdüğü kimlik bilgileri, 401 hata isteğiyle başarısız olmuş olan isteği yeniden göndermek için kullanılacaktır. Özel kimlik bilgisi sağlayıcısı yapılandırma, bu konunun sonraki bölümünde ele alınmıştır.
Özel kimlik bilgisi sağlayıcısının XML yapılandırması
Özel kimlik bilgisi sağlayıcısını yapılandırmak için, biri yapılandırma dosyası konumunu belirten iki XML dosyası ve özel kimlik bilgisi sağlayıcısı için yapılandırma bilgilerini içeren ikinci bir dosya kullanılır.
Yetkisiz 401 hatası döndürülürse, hata ayıklayıcı tarafından DbgCredentialProvider.dll çağrılır. Bu DLL, aşağıdaki işlemi kullanarak kimlik bilgisi sağlayıcılarını arar. Yapılandırma XML dosyalarının klasör konumunu sağlayan DbgCredentialProvider.dll ile aynı dizinde bulunması gereken bir dosya DbgCredentialProvider.config.xml açar.
DbgCredentialProvider.config.xml dosyasını bulmak için kullanılan arama davranışının gelecekte değişebileceğini unutmayın.
XML yapılandırma dosyası konumu - DbgCredentialProvider.config.xml
Yapılandırma XML dosyaları, DbgCredentialProvider.config.xml'de belirtildiği gibi klasör konumlarında yüklenir.
<?xml version="1.0" encoding="utf-8"?>
<!--
The config file is located next to the DbgCredentialProvider.dll.
-->
<Settings>
<Folders>
<!--
This is a list of the folders which should be provided as an absolute file path or
relative to the location of this config file.
-->
<Folder>CredentialProviders</Folder>
</Folders>
</Settings>
<Folders></Folders>
öğeleri altında birden fazla klasör listeleyebilirsiniz. Klasörler göreli veya mutlak yol olabilir. Göreli yol ise, DbgCredentialProvider.config.xml dosyasının konumuna göre belirlenir. Klasörler, listelenen sırayla sağlayıcılar için aranacaktır.
Yukarıda gösterilen geçerli örnekte, Klasörler koleksiyonunda yalnızca bir klasör "CredentialProviders" vardır ve bu da göreli bir yoldur.
Özel kimlik bilgisi sağlayıcısı için XML yapılandırma bilgileri
Belirtilen klasör konumu bulunduktan sonra CredentialProviders klasöründeki '*.xml' uzantılı tüm dosyalar numaralandırılır. XML dosyaları, hata ayıklayıcı için hangi hata ayıklayıcısı kimlik bilgisi sağlayıcılarının kullanılabilir olduğunu açıklar. Kimlik bilgisi sağlayıcılarının (DLL, EXE veya CMD/BAT betiklerinde uygulanır) konumu CredentialProviders XML dosyasında açıklanmıştır. Sağlayıcılar göreli veya mutlak yollar olabilir.
Birden çok özel kimlik bilgisi sağlayıcısı desteklenir. Hata ayıklayıcı her sağlayıcıdan kimlik bilgilerini ister ve başarılı döndüren ilk sağlayıcının kimlik bilgilerini kullanır.
XML dosyalarının numaralandırılma sırası belirtilmez.
Örnek DbgCredentialProvider_gcmw.xml dosyası, toplu iş dosyasının nasıl çağrılabileceğini gösterir.
<?xml version="1.0" encoding="utf-8"?>
<CredentialProviders>
<!--
This is a list of the provider modules which should be provided as an absolute file path or
relative to the location of this config file.
The provider is a DLL, EXE or CMD file.
-->
<CredentialProvider>PATCredentialProvider\PATCredentialProvider.bat</CredentialProvider>
</CredentialProviders>
Bu örnek XML, bir dll'nin nasıl çağrılabileceğini gösterir.
<?xml version="1.0" encoding="utf-8"?>
<CredentialProviders>
<!--
This is a list of the provider modules which should be provided as an absolute file path or
relative to the location of this config file.
The provider is a DLL, EXE or CMD file.
-->
<CredentialProvider>GCMW\DbgCredentialProvider_gcmw.dll</CredentialProvider>
</CredentialProviders>
Bu örnekte, yalnızca bir sağlayıcı olan DbgCredentialProvider_gcmw.dll, DbgCredentialProvider_gcmw.xml dosya konumuna göre GCMW klasöründe bulunmaktadır.
Özel kimlik bilgisi sağlayıcısını çağırmak için komut satırını kullanın
Bu bölümde, özel kimlik bilgisi sağlayıcısının EXE olarak nasıl uygulanabileceği (veya CMD/BAT dosya komut betiği aracılığıyla başlatılabileceği) açıklanmaktadır.
Sağlayıcı EXE veya CMD betiğinde uygulanıyorsa, birbiriyle birleştirilemeyen aşağıdaki komut satırı parametrelerini (büyük/küçük harfe duyarsız) işleyebilmesi gerekir.
- Al
- Silmek
- Mağaza
Komut Al
kimlik bilgilerini almak için Get komutu kullanılır. Kalan veriler standart giriş akışı aracılığıyla sağlayıcıya geçirilir.
Ek giriş verileri standart giriş akışı aracılığıyla sağlayıcıya geçirilir ve ardından giriş parametrelerinin sonunu işaretlemek için boş bir satır kullanılır.
Parametreler büyük/küçük harfe duyarlı değildir ve büyük ve küçük harflerin herhangi bir bileşimi kullanılabilir.
Bir hata error=zzzzz
aracılığıyla döndürülebilir
Protocol=http or https
Host=xxx
Path=yyy
ResourceKind=symbols or sources
Interactive=0 or 1
IsRetry=0 or 1
ParentHwnd=HWND
<empty line to mark the end of the input parameters>
Parametreleri alma
Alan | Tür | Açıklama |
---|---|---|
Protokol | LPCWSTR | HTTP veya HTTPS. Güvenliği artırmak için HTTPS'nin kullanılması kesinlikle önerilir. |
Ev sahibi | LPCWSTR | Konak sunucusunun adı, örneğin contoso.symbols.com |
Yol | LPCWSTR | Simgeler dizininin yolu, örneğin apis/symbol/symsrv . Çağıran/hata ayıklayıcı Yol'un hiçbir zaman '/' karakteriyle başlamadığından emin olur |
ResourceKind | LPCWSTR | "Simgeler" veya "kaynaklar" olabilir. Gelecekte ek kaynak türleri eklenebilir. Kimlik bilgisi sağlayıcısı uygulaması, kimlik bilgilerini alırken gerekli izinleri ayarlamak için bunu kullanabilir. Ayrıca, gelecekte kullanmak üzere kimlik bilgilerini önbelleğe almak için de kullanılabilir. |
Etkileşimli | Boolean | true - Kullanıcı arabirimini görüntülemede sorun yok, false - kullanıcı arabirimi yok. |
IsRetry | Bool | Doğru olduğunda sağlayıcının önbellekleri okumayı atlayıp yeni kimlik bilgileri alması gerekir |
ParentHwnd | HWND | Kimlik doğrulaması kullanıcı arabirimi görüntüleniyorsa üst HWND, örneğin 0x%I64x. Uygulamalar, üst HWND'yi ayarlamak için DBG_CREDENTIAL_PROVIDER_PARENT_HWND ortam değişkenini veya imagehlp/dbghelp SymSetParentWindow yöntemini kullanabilir. |
Tam URI/URL, listelenen parametreler kullanılarak <protocol>://<host>/<path>
birleştirilmesiyle oluşturulur. Örneğin: https://contoso.symbols.com/apis/symbol/symsrv
. İstek şöyle görünür:
protocol=https
host=contoso.symbols.com
path=apis/symbol/symsrv
resourceKind=symbols
isretry=false
issilent=false
parenthwnd=593598
<Followed by an empty line to indicate the end of the input data.>
Silmek
Kimlik bilgisi sağlayıcısı, kimlik bilgilerini önbelleğinden silmek için bu komutu kullanmayı seçebilir. Giriş parametreleri Get komutuyla aynıdır. Gerekli çıkış dönüş değeri yok. Hata döndürülebilir.
Mağaza
Kimlik bilgisi sağlayıcısı, kimlik bilgilerini önbelleğinde depolamak için bu komutu kullanmayı seçebilir. Giriş parametreleri Get komutuyla aynıdır. Çıkış dönüş değeri gerekmez. Hata döndürülebilir.
Yerel belirteç önbelleği ve yeniden deneme
Sağlayıcıya ilk istek için hata ayıklayıcısı parametresini isRetry=false
gönderir. Bazı sağlayıcılar belirteci yerel önbelleklerinden alıyor olabilir. Hata ayıklayıcı http isteğini bu belirteçle yeniden gönderdikten sonra sunucu 401 yanıtını yeniden döndürebilir. Bunun sebebi, belirtecin süresinin dolmuş olması olabilir. Ardından hata ayıklayıcı kimlik bilgisi sağlayıcısından yeni bir belirteç ister ve bu kez isRetry=true olur. Böyle bir durumda sağlayıcı önbelleğini kullanmamalı ve yepyeni bir belirteç almalıdır.
Etkileşimli ayar - kimlik doğrulaması kullanıcı arabirimi
Test laboratuvarları gibi etkileşimli olmayan bazı ortamlarda kullanıcı arabirimiyle etkileşim kuracak kullanıcı olmayabilir. Böyle bir durumda issilent parametresi true olacaktır. Bu parametre doğru olduğunda sağlayıcı herhangi bir kimlik doğrulaması veya başka bir kullanıcı arabirimi görüntülememelidir.
Test laboratuvarlarındaki veya uygulamalardaki betikler etkileşimli bayrağı denetlemek için aşağıdaki seçenekleri kullanabilir.
- "!sym prompts off" veya "!sym quiet" komutları. Daha fazla bilgi için bkz. !sym komut istemleri.
- sflags WinDbg veya cdb/kd (SYMOPT_NO_PROMPTS bayrağı) komut satırı parametresi.
- IDebugSymbols::SetSymbolOptions yöntemi (Simge Seçenekleri bölümünde açıklanan SYMOPT_NO_PROMPTS bayrağı)
- SymSetOptions'in imagehlp/dbghelp işlevi SYMOPT_NO_PROMPTS bayrağıyla.
Sessiz (etkileşim gerektirmeyen) sembol sunucusunu ayarla
Sessiz (etkileşimli olmayan) sembol sunucusunu ayarlamak için SymbolServerSetOptions işlevini kullanın.
SSRVOPT_UNATTENDED
TRUE olarak ayarlanırsa, SymSrv iletişim kutularını veya açılır pencereleri görüntülemez. Veriler YANLIŞ ise, SymSrv bağlantı kurarken bu grafik özellikleri görüntüler.
Kullanıcı Arabirimi Windows'larını yönetme
Bazı kimlik bilgileri sağlayıcıları kimlik doğrulaması kullanıcı arabirimi görüntüleyebilir. Öyleyse, bu kullanıcı arabiriminin ana hata ayıklayıcı penceresinde kalıcı bir iletişim kutusu olarak görünmesi için 'ParentHwnd' parametresini kullanmalıdır. Aksi takdirde, kimlik doğrulama kullanıcı arabirimi ana hata ayıklayıcı penceresinin arkasına gizlenebilir ve kullanıcıya hata ayıklayıcının "donduruldu" olduğu izlenimi verilebilir.
WinDbg'ye benzer bir hata ayıklayıcısı istemci uygulaması, üst HWND'yi ayarlamak için DBG_CREDENTIAL_PROVIDER_PARENT_HWND ortam değişkeni veya imagehlp/dbghelp SymSetParentWindow yöntemini kullanabilir. Ayrıca, IDebugAdvanced2::Request iletisini HWND değerini UINT32'ye dönüştürülmüş olarak kullanabilirsiniz.
Dönüş değeri gereksinimleri
EXE veya CMD/BAT betiği, çıkış akışı aracılığıyla kullanıcı adını ve parolayı aşağıdaki gibi döndürmelidir:
username=aaa
password=bbb - where the password can be a password or PAT
CredentialKind
Kimlik doğrulama isteği CredentialKinddöndürür. CredentialKind için iki seçenek vardır.
- Temel Kimlik Doğrulaması: RFC 7617'de tanımlanır. Kimlik bilgileri, Base64 kullanılarak kodlanmış kullanıcı kimliği/parola çiftleri olarak iletilir.
username=xxx
credentialkind=Basic
password=yyy --> This can be a password or a PAT token
- Taşıyıcı Kimlik Doğrulaması: RFC 6750'de tanımlanır. Taşıyıcı belirteçleri, OAuth 2.0 korumalı kaynaklara erişmek için HTTP isteklerinde kullanılır.
username=xxx
credentialkind=Bearer
header=Bearer <TOKEN_GOES_HERE> ---> Usually OAuth2 tokens begin with "ey" and it is a very long string
Örnek CMD dosyası
HTTP kimlik doğrulaması üst bilgisi döndüren bir CMD dosyası örneği aşağıda verilmiştir:
CredentialProviders klasöründe bulunan OAuth2CredentialProvider.xml dosyası:
<?xml version="1.0" encoding="utf-8"?>
<CredentialProviders>
<CredentialProvider ApiVersion="2.0.0" >OAuth2CredentialProvider\OAuth2CredentialProvider.cmd</CredentialProvider>
</CredentialProviders>
OAuth2CredentialProvider klasöründe bulunan OAuth2CredentialProvider.cmd dosyası:
@echo off
echo username=UserName@domain.com
echo header=Bearer <TOKEN_GOES_HERE>
Özel sağlayıcıyı test etme
CMD veya EXE dosyasında bulunan özel bir sağlayıcı yazıyorsanız, komutları kullanarak bir konsol penceresinden başlatarak bunu test edebilirsiniz. Örneğin:
DebuggerCredentialManager.exe Get
Bu işlem uygulamayı başlatır ve bunun gibi bir şey yazdırır ve kullanıcı girişini bekler (boş bir satır, kullanıcı girişinin sonunu gösterir).
[Information] [DebuggerCredentialProvider.102949]Microsoft Debugger Credential Manager version 2024.0409.02656.285 (Windows, .NET 6.0.29) 'get'
Konsol penceresi giriş akışına girdiğiniz bilgilere bir örnek aşağıda verilmiştir. Büyük ve küçük harflerin herhangi bir bileşiminde girilebilir.
protocol=https
host=contoso.symbols.com
path=apis/symbol/symsrv
resourceKind=symbols
isretry=false
issilent=false
parenthwnd=593598
Ardından enter tuşuna iki kez basarak boş bir satır gönderin ve kullanıcı girişinin sonunu belirtin.
Sağlayıcı, standart çıkış akışı aracılığıyla yanıt verir.
[Verbose] [DebuggerCredentialProvider.103258]AzureCredentialProvider - Attempting to acquire bearer token using provider 'Msal Cache'
[Verbose] [DebuggerCredentialProvider.103300]Token expiration data - current UTC time:9/18/2024 5:33:00 PM, ExpiresOn: 9/18/2024 6:43:25 PM
[Information] [DebuggerCredentialProvider.103300]AzureCredentialProvider - Acquired bearer token using 'Msal Cache'
protocol=https
host=contoso.symbols.com
path=apis/symbol/symsrv
username=UserName@domain.com
credentialkind=Bearer
header=Bearer eyJ0eXAi....
<empty line>
Hata ayıklayıcı, anahtarın protokol, ana bilgisayar, yol, kullanıcı adı, credentialkind veya üst bilgi olduğu desen key=value
ile eşleşmeyen satırları yoksayar.
Anahtar değer çiftlerinde büyük/küçük harf önemsenmez. Hata ayıklayıcı, boş bir satırı girişin sonu olarak değerlendirir.
Hizmet sağlayıcı tanılama bilgileri
Sağlayıcılar, tanılama bilgilerini çıkış akışına yazdırmayı seçebilir. Hata ayıklayıcı bunu yoksayar, ne de bunları kullanıcıya göstermeyecek. Burada gösterilen ek bilgi örnekleri yalnızca çizim amaçlıdır. Diğer sağlayıcılar diğer tanılama bilgilerini yazdırabilir veya hiçbir şey yazdırmayabilir.
PAT jetonu döndüren PowerShell örnek betiği
İşte bir PAT belirteci döndürmeye yönelik bir PS betiği örneği.
Dosya PatCredentialProvider.xml, PATCredentialProvider.bat'i CredentialProvider olarak yapılandırır.
<?xml version="1.0" encoding="utf-8"?>
<CredentialProviders>
<CredentialProvider ApiVersion="2.0.0">PATCredentialProvider\PATCredentialProvider.bat</CredentialProvider>
</CredentialProviders>
PATCredentialProvider klasöründe bulunan Dosya PATCredentialProvider.bat ve PATCredentialProvider.ps1çağırır.
@echo off
<PATH_TO_POWERSHELL>\PowerShell.exe -NoProfile -executionpolicy Unrestricted -WindowStyle Hidden -File "%~dp0\PATCredentialProvider.ps1"
PATCredentialProvider.ps1 da PATCredentialProvider klasöründe bulunur.
<#
.SYNOPSIS
Given input, parses to find out which symbol server we want credentials for, and searches the Microsoft Credential Manager for those credentials.
If found, prints the credentials to standard output. If not, prints error.
.INPUT
Delivered through standard input:
protocol=http or https
host=xxx ex. host=contoso.symbols.com
path=yyy ex. path=apis/symbol/symsrv
resourceKind=symbols
isretry=false
issilent=false
parenthwnd=593598
<empty line to mark the end of the input parameters>
.OUTPUT
Delivered through standard output:
username=aaa
password=bbb - where the password can be a password or PAT. When PAT is returned the username will be any name (not necessarily the name of the currently logged in user)<!--[SuppressMessage("Microsoft.Security", "CS001:SecretInline", Justification="It's an example")]-->
<empty line to mark the end of the output parameters>
#>
$logDirectory = (Get-Item Env:LoggingDirectory).Value
$logFile = Join-Path $logDirectory "credProviderLog.txt"
try
{
"Entering Credential Provider" | Out-File $logFile -Append
$lines = While($line=Read-Host) {$line}
$lines | Out-File $logFile -Append
if (!(Get-Module "CredentialManager"))
{
"Installing module" | Out-File $logFile -Append
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module CredentialManager -force -Scope CurrentUser
}
$pathLine = $lines | Where-Object {$_.StartsWith("path=")} | Select-Object -First 1
"Found path line: $pathLine" | Out-File $logFile -Append
[regex]$regex="path=(?<ServerName>.*)"
$pathLine -Match $regex
$symbolPath = "symbol:$($Matches.ServerName)"
"Found symbol path: $symbolPath" | Out-File $logFile -Append
$PAT = Get-StoredCredential -Target $symbolPath -AsCredentialObject
if ($PAT)
{
"Found PAT!" | Out-File $logFile -Append
Write-Host "username=placeholder"
Write-Host "password=$($PAT.Password)"; # For OAuth 2 tokens You can change to output header=Bearer TOKEN
Write-Host
}
else
{
"Could not locate PAT for Symbol Server: $symbolPath" | Out-File $logFile -Append
Write-Host "error=Could not locate PAT for Symbol Server: $symbolPath"
}
}
catch [System.SystemException]
{
"ERROR" | Out-File $logFile -Append
$_ | Out-File $logFile -Append
}
DLL olarak uygulanan kimlik bilgisi sağlayıcıları için C++ API'si
Özel kimlik bilgisi sağlayıcısı bir DLL'de uygulanıyorsa, ortak arabirim kimlik bilgisi sağlayıcılarının uyması gerekenler aşağıda açıklanmaktadır. Sağlayıcı bir DLL'de uygulandıysa, GetUserCredentials metodunu dışarı aktarmalıdır.
namespace Debugger::CredentialProvider::Provider
konumunda yer alırlar.
Gerekli DbgCredentialProviderImpl.h üst bilgi dosyası Windows SDK ile yayımlanır. SDK'yı indirme hakkında bilgi için bkz. Windows SDK ve SDK Insider Preview.
MessageErrorLevelKind enum türleri
// The caller of this method should not terminate the message with '\r' or '\n' characters
// (which makes this method similar to PrintLine)
typedef void (*DbgPrintMessageFn)(_In_ MessageErrorLevelKind errorLevel, _In_ PCWSTR message);
enum class MessageErrorLevelKind : uint8_t
{
Info = 0,
Warning,
Error
};
YetkilendirmeCevapSonuçTürü
enum CredentialResponseResultKind
{
Success = 0,
NoProviders, // There are no installed providers or can't launch 3rd party provider
ProviderNotApplicable, // the provider can't handle requests to the provided URL
Error
};
struct GetUserCredentialsRequest
GetUserCredentialsRequest'i depolamak için bir yapı kullanılır. Yukarıda GetUserCredentialsRequest parametreleri tablosunda açıklandığı gibi aynı parametreleri kullanır.
struct GetUserCredentialsRequest
{
LPCWSTR Protocol; // The full request URL can be built from Protocol, Host and Path as follows:
LPCWSTR Host; // Protocol://Host/Path
LPCWSTR Path; // The caller/debugger will make sure Path never starts with '/' character
LPCWSTR ResourceKind; // It can be "symbols", "sources", etc.
// The credential provider implementation may use this to adjust
// the required permissions when acquiring credentials. It also may be used
// to cache credentials for future use.
bool Interactive; // true - display UI is ok, false - no UI.
// Refer to the explanations above on how to setup a non interactive environment
bool IsRetry; // When true the provider may skip reading the caches and get new credentials
HWND ParentHwnd; // The parent HWND if an authentication UI is displayed.
// The applications can use DBG_CREDENTIAL_PROVIDER_PARENT_HWND environment variable
// or imagehlp/dbghelp SymSetParentWindow method to setup the parent HWND.
DbgPrintMessageFn PrintMessageFn;
}
GetUserCredentials işlevi
Kimlik bilgilerini istemek için, semboller için HTTP isteğinde sembol sunucusuna gönderilecek olan GetUserCredentials işlevi kullanılır.
HRESULT WINAPI GetUserCredentials(
_In_ GetUserCredentialsRequest const & request,
_Inout_ GetUserCredentialsResponse * pResponse);
Bu yöntemin çağıranı (hata ayıklayıcısı), istek ve yanıt parametrelerini sağlar. Çağıran, UserName, Password ve ErrorMessage'ın yöntem girdisinde nullptr olmasını sağlar.
Uygulamanın UserName, Password, ErrorMessage (isteğe bağlı) ve Result değerlerini doldurması gerekir.
GetUserCredentialsResponse sınıfı
GetUserCredentialsResponse sınıfı burada gösterilmiştir.
class GetUserCredentialsResponse final
{
public:
CredentialResponseResultKind Result = CredentialResponseResultKind::Error;
BSTR UserName = nullptr;
BSTR Password = nullptr;
BSTR HttpAuthenticationHeader = nullptr;
BSTR ErrorMessage = nullptr;
GetUserCredentialsResponse() = default;
GetUserCredentialsResponse(GetUserCredentialsResponse const&) = delete;
GetUserCredentialsResponse& operator=(GetUserCredentialsResponse const&) = delete;
GetUserCredentialsResponse(GetUserCredentialsResponse&& other) noexcept
{
Result = other.Result;
UserName = other.UserName;
Password = other.Password;
HttpAuthenticationHeader = other.HttpAuthenticationHeader;
ErrorMessage = other.ErrorMessage;
other.Release();
}
GetUserCredentialsResponse& operator=(GetUserCredentialsResponse&& other) noexcept
{
if (this != addressof(other))
{
Clear();
Result = other.Result;
UserName = other.UserName;
Password = other.Password;
HttpAuthenticationHeader = other.HttpAuthenticationHeader;
ErrorMessage = other.ErrorMessage;
other.Release();
}
return (*this);
}
~GetUserCredentialsResponse()
{
Clear();
}
void Clear()
{
SecureSysFreeString(UserName);
SecureSysFreeString(Password);
SecureSysFreeString(HttpAuthenticationHeader);
SecureSysFreeString(ErrorMessage);
}
private:
template <class _Tp>
_Tp* addressof(_Tp& __x) noexcept
{
return reinterpret_cast<_Tp*>(
const_cast<char*>(&reinterpret_cast<const volatile char&>(__x)));
}
void Release() noexcept
{
Result = CredentialResponseResultKind::Error;
UserName = nullptr;
Password = nullptr;
ErrorMessage = nullptr;
HttpAuthenticationHeader = nullptr;
}
void SecureSysFreeString(_Inout_ BSTR& bstrString)
{
if (bstrString != nullptr)
{
size_t const length = wcslen(bstrString);
SecureZeroMemory(bstrString, length * sizeof(wchar_t));
SysFreeString(bstrString);
bstrString = nullptr;
}
}
};