Credential Provider v2 API - Feststellen, dass Other User Tile ausgewählt



  • Das ist zu einfach! 😃

    Das geht mit Sicherheit, ist aber die wirklich unelegante Lösung. Wenn ich aber nichts anderes finde, dann mach ich das so. Da hätte man auch selbst drauf kommen können.

    Also danke für zumindest diesen Rettungsanker.


  • Mod

    Khalidjian schrieb:

    Das Beispiel im Änderungsdokument suggeriert ja, dass es geht. Danke für den Tip mit dem Microsoft Ticket, mal sehen ob ich das nutzen kann.
    Ich danke dir aber für deine Mühe Martin.

    Nö. Für mich nicht.
    Es sugerriert nur, dass Sie kein #ifdef genommen haben, was das ganze klar gemacht hätte... 😉 oder eine const Definition.

    Die Frage ist, wie oft wird die Funktion aufgerufen. Vermutlich eben nur einmal. Wie also soll man also "alternativ" etwas zurück geben.
    Insofern hat hustbaer vermutlich recht mit seinem Vorschlag..



  • Also mit der Funktion GetAccountOptions von ICredentialProviderUserArray lässt sich feststellen, ob die "Anderer Benutzer" Kachel angezeigt wird.
    Das müsste sich benutzen lassen um es dynamisch zu machen. Ich muss nur noch herausbekommen wo 😃

    Siehe dazu MSDN:
    https://msdn.microsoft.com/en-us/library/windows/desktop/hh706924%28v=vs.85%29.aspx

    Edit: ich bekomme von GetAccountOptions keinen Fehler zurück, aber ein undocumentiertes Value in der Umgebung der Domäne hier, nämlich "3" Während es tatsächlich NONE(0) ist, wenn ich es auf einem nicht Domänenrechner ausprobiere.



  • Mir ist übrigens jetzt bei meinen Lokalen Tests aufgefallen, dass auch hier nur die 1. Kachel meinen Credentialprovider hat, der zweite Lokale Nutzer hat ihn auch nicht.
    Das überzeugt mich davon, dass es nicht gewollt ist, einen zweiten CredentialProvider zu registrieren, denn Microsoft kann nicht erwarten, dass man für jeden lokalen Nutzer einen CredentialProvider registriert. Zumindest wenn sie einen funken Vernunft haben und in der Datei ist ja auch von user(s) die Rede, jetzt muss ich nur herausbekommen, wie ich bei "GetUserSID" mehr als eine SID zurück gebe, bzw. erst einmal dort hin bekomme, dass ich mehr als einem User meinen CredentialProviderCredential nutzen lassen will.



  • Lange hat es gedauert, aber ich habe eine Lösung gefunden. Der Grundstock ist hier beschrieben: http://stackoverflow.com/questions/31241665/how-to-show-icredentialprovidercredentialv2-on-more-than-one-user-tile-on-the-ot .

    Wenn man sich am Beispiel orientiert, muss man in EnumerateCredentials ein Array con ICredentialProviderCredential erstellen, oder dem was man benutzen möchte.
    Dieses Array muss man um eins vergrößern wenn ICredentialProviderUserArray::GetAccountOptions != CPAO_NONE ist und dafür ein weiteres Credential erstellen, indem dann bei "GetUserSID" hr =S_FALSE zurück gegeben wird.

    Vielen Dank euch!



  • Könntest Du den Code posten?
    Danke



  • Das kann ich leider nicht mehr. Das Projekt ist nicht mehr unter meinen fittichen, weshalb es nicht mehr mein Code ist. Den ich Posten könnte. Außerdem muss ich gestehen, da man an vielen stellen Kleinigkeiten machen muss, weiß ich auch nicht genau, wie ich es ordentlich posten kann, ohne zu große Verwirrung zu stiften.

    Hast du es denn schon geschafft, dass dein Credentialprovider bei mehr als einem User angezeigt wird?



  • Khalidjian schrieb:

    Hast du es denn schon geschafft, dass dein Credentialprovider bei mehr als einem User angezeigt wird?

    Leider nein. Die beiden Funktionen die du angespreochen hast schauen in meinem Sample so aus. Wenn ich in GetUserSid gleich S_FALSE zurückgebe (Zeile 5), dann kommt der Provider bei "Anderer Benutzer", nicht aber bei namentlich bekannten Benutzern. Workaround wären halt zwei Provider ... ist aber nicht schön.

    // Gets the SID of the user corresponding to the credential.
    HRESULT CSampleCredential::GetUserSid(_Outptr_result_nullonfailure_ PWSTR *ppszSid)
    {
        *ppszSid = nullptr;
        //return S_FALSE
    
        HRESULT hr = E_UNEXPECTED;
        if (_pszUserSid != nullptr)
        {
    		hr = SHStrDupW(_pszUserSid, ppszSid);
        }
        // Return S_FALSE with a null SID in ppszSid for the
        // credential to be associated with an empty user tile.
    	else
    	{
    		*ppszSid = nullptr;
    		hr = S_FALSE;
    	}
    
        return hr;
    }
    
    HRESULT CSampleProvider::_EnumerateCredentials()
    {
    	HRESULT hr = E_UNEXPECTED;
        if (_pCredProviderUserArray != nullptr)
        {		
    		DWORD dwUserCount;
            _pCredProviderUserArray->GetCount(&dwUserCount);
            if (dwUserCount > 0)
            {
                ICredentialProviderUser *pCredUser;
                hr = _pCredProviderUserArray->GetAt(0, &pCredUser);
                if (SUCCEEDED(hr))
                {
                    _pCredential = new(std::nothrow) CSampleCredential();
                    if (_pCredential != nullptr)
                    {
                        hr = _pCredential->Initialize(_cpus, s_rgCredProvFieldDescriptors, s_rgFieldStatePairs, pCredUser);
                        if (FAILED(hr))
                        {
                            _pCredential->Release();
                            _pCredential = nullptr;
                        }
                    }
                    else
                    {
                        hr = E_OUTOFMEMORY;
                    }
                    pCredUser->Release();
                }
            }
        }
        return hr;
    }
    


  • Also der Knackpunkt ist in deinem zweiten Codebeispiel in Zeile 14:

    _pCredential = new(std::nothrow) CSampleCredential();
    

    Du musst im Header aus:

    CSampleCredential* _pCredential;
    

    ein Array/einen Vektor von Credentials machen. Du hast also nur einen Provider, der aber mehrere ICredentialProviderCredential Objekte zur Verfügung stellt.
    Dann musst du für jeden Nutzer in dwUserCount einmal ein Credential erzeugen:

    for(DWORD i = 0; i < dwUserCount; ++i)
            {
                ICredentialProviderUser *pCredUser;
                hr = _pCredProviderUserArray->GetAt(i, &pCredUser);
                if (SUCCEEDED(hr))
                {
                    _pCredential->push_back(new(std::nothrow) CSampleCredential());
                    if (_pCredential->at(i) != nullptr)
                    {
                        hr = _pCredential->at(i)->Initialize(_cpus, s_rgCredProvFieldDescriptors, s_rgFieldStatePairs, pCredUser);
                        if (FAILED(hr))
                        {
                            _pCredential->Release();
                            _pCredential = nullptr;
                        }
                    }
                    else
                    {
                        hr = E_OUTOFMEMORY;
                    }
                    pCredUser->Release();
                }
            }
    

    Das oben ist nur wie es vom Prinzip her am Ende ungefähr aussehen müsste. Um das sauber zu machen, musst du dir natürlich überlegen ob du ein Array von ICredentialProviderCredentials möchtest oder einen Vektor oder eine andere Art von Container.
    Ich hatte es mit einem std::vektor gelöst. Der Zugriff im Interface am Rechner hatte aber noch einmal ein paar Tücken. Da musst du schauen, wo du überall auf das Credential zugreifst und wie du die Ordnung beibehälst, ebsonders, wenn sich die Anzahl während des Logins ändern könnte. Das war bei uns dann auch der Fall.



  • danke, das schau ich mir mal genau an


Anmelden zum Antworten