I am writing custom windows credential provider using c++ with the help of sample provided by windows CredentialProvider2
I modified CredentialCount and CredentialAt in provider class to return 3 users. Those 3 users appear below sign-in options link. I expect them to display left bottom of the screen.
HRESULT CSampleProvider::GetCredentialCount(
_Out_ DWORD *pdwCount,
_Out_ DWORD *pdwDefault,
_Out_ BOOL *pbAutoLogonWithDefault)
{
*pdwDefault = CREDENTIAL_PROVIDER_NO_DEFAULT;
*pbAutoLogonWithDefault = FALSE;
if (_fRecreateEnumeratedCredentials)
{
_fRecreateEnumeratedCredentials = false;
_ReleaseEnumeratedCredentials();
_CreateEnumeratedCredentials();
}
*pdwCount = 3;
return S_OK;
}
HRESULT CSampleProvider::GetCredentialAt(
DWORD dwIndex,
_Outptr_result_nullonfailure_ ICredentialProviderCredential **ppcpc)
{
HRESULT hr = E_INVALIDARG;
*ppcpc = nullptr;
if(ppcpc){
hr = _pCredential->QueryInterface(IID_PPV_ARGS(ppcpc));
}
return hr;
}
This is what I get
But I want to display the list of users in the left bottom of the screen. I will be a great help if you suggest me the changes are required to make it display left bottom on the screen?
Related
I use sample code of "Credential Providers in Windows 10". I develop my code and change it very good.
But I have some problem with it:
It is not enable (Show tile) for all users in my windows. (Show for one user only)
I See this questions:
https://stackoverflow.com/a/31247811/3477587
Credential provider not displayed for all users (Other user included)
So I change my code but when use from my DLL win-login don't load and I must delete in in safe-mode to I can enter to my windows without Credential Providers.
I change my code as follow:
std::vector<CSamanCredential*> _pCredential; // SampleV2Credential
HRESULT CSamanProvider::GetCredentialAt(
DWORD dwIndex,
_Outptr_result_nullonfailure_ ICredentialProviderCredential** ppcpc)
{
HRESULT hr = E_INVALIDARG;
*ppcpc = nullptr;
hr = _pCredential[dwIndex]->QueryInterface(IID_PPV_ARGS(ppcpc));
return hr;
}
HRESULT CSamanProvider::GetCredentialCount(
_Out_ DWORD* pdwCount,
_Out_ DWORD* pdwDefault,
_Out_ BOOL* pbAutoLogonWithDefault)
{
*pdwDefault = CREDENTIAL_PROVIDER_NO_DEFAULT;
*pbAutoLogonWithDefault = FALSE;
if (_fRecreateEnumeratedCredentials)
{
_fRecreateEnumeratedCredentials = false;
_ReleaseEnumeratedCredentials();
_CreateEnumeratedCredentials();
}
DWORD dwUserCount = 0;
HRESULT hr;
if (_pCredProviderUserArray != nullptr) {
hr = _pCredProviderUserArray->GetCount(&dwUserCount);
}
if ((dwUserCount == 0) || (IsOS(OS_DOMAINMEMBER) == 1)) {
dwUserCount += 1;//display additional empty tile
}
*pdwCount = dwUserCount;
return S_OK;
}
void CSamanProvider::_ReleaseEnumeratedCredentials()
{
DWORD dwUserCount;
_pCredProviderUserArray->GetCount(&dwUserCount);
for (DWORD i = 0; i < dwUserCount; i++) {
if (_pCredential[i] != nullptr)
{
_pCredential[i]->Release();
_pCredential[i] = nullptr;
}
}
}
So I change other place in my code but I don't get result.
You must follow instructions in the posts you mentioned.
As a indirect response to ICredentialProviderSetUserArray::SetUserArray you must prepare tile for each user in the supplied list.
Later your tiles will be asked for ICredentialProviderCredential2::GetUserSid.
There your tile must return one of SIDs from the list of previous step.
When I was implementing this logic had to redesign a huge part of my code to support this feature.
I read this code. This is very helpful for knowing instruction and other details.
https://github.com/multiOTP/multiOTPCredentialProvider
This code (C++) active CP for all user on computer.
Thank you
Please understand my lack of writing skills.
I am testing to make a custom credential provider.
I want to create a CommandLink that does the same thing with the submit button.
I want to log on through the CommandLink separately from the Submit button.
Currently, only the custom credential provider is exposed through the providerFilter::Filter(CREDENTIAL_PROVIDER_USAGE_SCENARIO cpus, DWORD dwFlags, GUID* rgclsidProviders, BOOL* rgbAllow, DWORD cProviders).
Click [anathor longon button] to log on.
This is my sample code:
HRESULT CSampleCredential::CommandLinkClicked(DWORD dwFieldID)
{
HRESULT hr = S_OK;
DWORD dwResult = 0;
if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors) &&
(CPFT_COMMAND_LINK == _rgCredProvFieldDescriptors[dwFieldID].cpft))
{
HWND hwndOwner = nullptr;
switch (dwFieldID)
{
case SFI_ANATHOR_SUBMIT_LINK:
dwResult = function_foo();
if(dwResult == 1) {
Call GetSerialization()...?
Run the logon.
}
break;
// ...
}
}
}
Because you are writing credential provider, than you are already implementing ICredentialProvider interface and its Advise method:
virtual HRESULT STDMETHODCALLTYPE Advise(
/* [annotation][in] */
_In_ ICredentialProviderEvents *pcpe,
/* [annotation][in] */
_In_ UINT_PTR upAdviseContext) = 0;
The first argument is pointer to events interface ICredentialProviderEvents which have only one method: CredentialsChanged.
Your task is to grab credentials from user (login/password) store them inside your internals and call this method.
On the next turn your provider will be called this method:
virtual HRESULT STDMETHODCALLTYPE GetCredentialCount(
/* [annotation][out] */
_Out_ DWORD *pdwCount,
/* [annotation][out] */
_Out_ DWORD *pdwDefault,
/* [annotation][out] */
_Out_ BOOL *pbAutoLogonWithDefault) = 0;
Your task is to return the correct values in pdwDefault and pbAutoLogonWithDefault parameters (my suggest is 0 and TRUE).
Than your class that implementing ICredentialProviderCredential interface will be immediately called for GetSerialization method.
Here you can return already stored credentials.
Newbie here,
For the people who don't understand #Alexander 's explanation (like me several days ago), I recommend to read the Sample Harware Event Credential Provider. You need the 3rd class that is not inherited from ICredentialProvider or ICredentialProviderCredential. This is an independent class which is not related to both of them. I use this class to call the CredentialsChanged function.
So, TL;DR this is how I implement it:
Make a condition inside the ICredentialProvider's GetCredentialCount function like this
HRESULT CSampleCredentialProvider::GetCredentialCount(
DWORD* pdwCount,
DWORD* pdwDefault,
BOOL* pbAutoLogonWithDefault
)
{
//SavedCredentialInfo is just a simple Bool variable
if (_pCredential->SavedCredentialInfo == true)
{
*pdwCount = 1;
*pdwDefault = 0;
*pbAutoLogonWithDefault = TRUE;
}else{
*pdwCount = 1;
*pdwDefault = 0;
*pbAutoLogonWithDefault = FALSE;
}
return S_OK;
}
Save the credential (I use username & password) as a variable (string) inside my custom class that inherit ICredentialProviderCredential
HRESULT CGuardianCredential::CommandLinkClicked(DWORD dwFieldID)
{
if (dwFieldID < ARRAYSIZE(_rgCredProvFieldDescriptors) &&
(CPFT_COMMAND_LINK == _rgCredProvFieldDescriptors[dwFieldID].cpft)) {
this._username = "Ramon";
this._domain = "DESKTOP-937SDJ";
this._password = "MyPassword";
}
. . .
}
Call the 3rd class's function that call the ICredentialProvider's CredentialsChanged function
HRESULT CGuardianCredential::CommandLinkClicked(DWORD dwFieldID)
{
. . .
_commandWindow->callOnChange();
}
Then inside the commandWindow's class
BOOL CCommandWindow::callOnChange()
{
_pProvider->OnConnectStatusChanged();
return true;
}
Then you have it
I want to get the width and hight of a image file on a WPD via IPortableDeviceValues.
According to the Windows Dev Center every object whose type is WPD_CONTENT_TYPE_IMAGE (which they are) requires to provide WPD_MEDIA_WIDTH/WPD_MEDIA_HEIGHT but I always get a error.
HRESULT MyPortableDevice::getIntValue(IPortableDeviceProperties* properties, PCWSTR objectID, const PROPERTYKEY& key, DWORD* value)
{
ComPtr<IPortableDeviceValues> objectProperties;
ComPtr<IPortableDeviceKeyCollection> propertiesToRead;
HRESULT hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&propertiesToRead));
if (SUCCEEDED(hr)) {
HRESULT tempHr = S_OK;
tempHr = propertiesToRead->Add(key);
}
if (SUCCEEDED(hr)) {
hr = properties->GetValues(objectID,
propertiesToRead.Get(),
&objectProperties);
}
if (SUCCEEDED(hr)) {
ULONG intValue = 0;
hr = objectProperties->GetUnsignedIntegerValue(key, &intValue);
if (SUCCEEDED(hr)) {
value = &intValue;
intValue = 0;
}
}
return hr;
I always get a error value from
hr = objectProperties->GetUnsignedIntegerValue(key, &intValue);
hr = 0x80070490 and I can't find this error code here
Does anyone know what's wrong?
The error you got is:
Error code: (HRESULT) 0x80070490 (2147943568) - Element not found.
The reason you got this error most probably is that actually phone apps developers usually just ignore some of properties.
I have connected my phone to PC and checked some images with WPD Information Tool , and I get only such fields for .jpg screenshot:
I think in most cases you need to read content of the picture to stream and check it's parameters directly. Maybe in some formats you can read only some "header" part and get WIDTH and HEIGHT from there.
I have a log in screen when my application starts and would like the cursor to be waiting in the user name text box to type (without clicking). I was able to focus the cursor after the grid loads:
HRESULT MainPage::OnLoaded(__in IXRDependencyObject* pRoot)
{
UNREFERENCED_PARAMETER(pRoot);
HRESULT hr = InitializeComponent();
if (FAILED(hr))
{
goto Error;
}
if (m_pLogin)
{
m_pLogin->AddLoadedEventHandler(CreateDelegate(this, &MainPage::Login_Loaded));
}
Error:
return hr;
} // OnLoaded
HRESULT MainPage::Login_Loaded (IXRDependencyObject* pSender, XRRoutedEventArgs* pArgs)
{
HRESULT hr = S_OK;
m_pUserName->Focus(&pBool);
return hr;
}
This allows me to type but the cursor isn't actually visible.
I have seen other threads explaining that the browser plugin must have focus first, but this is an embedded silverlight application (C++) and not a silverlight webpage (C#). I cannot figure out how to set focus to the application when it starts without using the mouse. Any suggestions?
I was not able to accomplish this without a mouse click - but I used SendInput to synthesize a mouse click so the user doesn't have to.
HRESULT MainPage::OnLoaded(__in IXRDependencyObject* pRoot)
{
UNREFERENCED_PARAMETER(pRoot);
HRESULT hr = InitializeComponent();
if (FAILED(hr))
{
goto Error;
}
if (m_pLogin)
{
m_pLogin->AddLoadedEventHandler(CreateDelegate(this, &MainPage::Login_Loaded));
m_pLogin->AddMouseLeftButtonUpEventHandler(CreateDelegate(this, &MainPage::Login_MouseLeftButtonUp));
}
Error:
return hr;
} // OnLoaded
HRESULT MainPage::Login_Loaded (IXRDependencyObject* pSender, XRRoutedEventArgs* pArgs)
{
HRESULT hr = S_OK;
// execute mouse click
INPUT ip;
ip.type = INPUT_MOUSE;
ip.mi.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE;
SendInput(1,&ip,sizeof(INPUT));
ip.mi.dwFlags = MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE;
SendInput(1,&ip,sizeof(INPUT));
return hr;
}
HRESULT MainPage::Login_MouseLeftButtonUp (IXRDependencyObject* pSender, XRMouseButtonEventArgs* pArgs)
{
HRESULT hr = S_OK;
m_pUserName->Focus(&pBool);
return hr;
}
I wanted to programatically show the below Windows Security dialog from C++. Wondering which Windows API is to be used to prompt this dialog to get the proxy credentials instead of building a custom dialog box.
I am able to show WindowsSecurity dialog to ask for Proxy credentials. Here is the code. Will have to fine tune it bit but it is working.
void getCredentials(const char * proxyIp, int proxyPort, char * proxType, QString &user, QString &password)
{
Log.info("Credentials", L"About to read credentials for [%hs] [%d] [%hs]",proxyIp,proxyPort,proxType);
HRESULT hr = S_OK;
DWORD dwResult;
PVOID pvInAuthBlob = NULL;
ULONG cbInAuthBlob = 0;
PVOID pvAuthBlob = NULL;
ULONG cbAuthBlob = 0;
CREDUI_INFOW ui;
ULONG ulAuthPackage = 0;
BOOL fSave = FALSE;
TCHAR pszName[CREDUI_MAX_USERNAME_LENGTH+1];
TCHAR pszPwd[CREDUI_MAX_PASSWORD_LENGTH+1];
TCHAR domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH+1];
DWORD maxLenName = CREDUI_MAX_USERNAME_LENGTH+1;
DWORD maxLenPassword = CREDUI_MAX_PASSWORD_LENGTH+1;
DWORD maxLenDomain = CREDUI_MAX_DOMAIN_TARGET_LENGTH+1;
// Display a dialog box to request credentials.
ui.cbSize = sizeof(ui);
ui.hwndParent = GetConsoleWindow();
ui.pszMessageText = L"The Proxy Server requires user name and password";
ui.pszCaptionText = L"Proxy Authentication";
ui.hbmBanner = NULL;
dwResult = CredUIPromptForWindowsCredentialsW(
&ui, // Customizing information
0, // Error code to display
&ulAuthPackage, // Authorization package
pvInAuthBlob, // Credential byte array
cbInAuthBlob, // Size of credential input buffer
&pvAuthBlob, // Output credential byte array
&cbAuthBlob, // Size of credential byte array
&fSave, // Select the save check box.
CREDUIWIN_GENERIC
);
if (dwResult == NO_ERROR)
{
Log.info("Credentials", L"cred read success");
CredUnPackAuthenticationBufferW(0,
pvAuthBlob,
cbAuthBlob,
pszName,
&maxLenName,
domain,
&maxLenDomain,
pszPwd,
&maxLenPassword);
SecureZeroMemory(pvAuthBlob, cbAuthBlob);
CoTaskMemFree(pvAuthBlob);
pvAuthBlob = NULL;
Log.info("Credentials", L"u [%ls] p [%ls] d[%ls]",QString::fromWCharArray(pszName).toStdWString().c_str(),
QString::fromWCharArray(pszPwd).toStdWString().c_str(),
QString::fromWCharArray(domain).toStdWString().c_str());
user = QString::fromWCharArray(pszName).toStdWString();
password = QString::fromWCharArray(pszPwd).toStdWString();
SecureZeroMemory(pszName, sizeof(pszName));
SecureZeroMemory(pszPwd, sizeof(pszPwd));
}else
{
Log.info("Credentials", L"cred read fail");
hr = HRESULT_FROM_WIN32(dwResult);
if (pvInAuthBlob)
{
SecureZeroMemory(pvInAuthBlob, cbInAuthBlob);
CoTaskMemFree(pvInAuthBlob);
pvInAuthBlob = NULL;
}
}
}
You could try with CredUIPromptForCredentials ( small example of usage here ) or CredUIPromptForWindowsCredentials