78061

C++ Windows Credential Provider Progress Screen

Question:

I am developing a custom credential provider and I have to show a progress screen with a cancel button. I have seen in some credentials providers and pgina plugins that a screen is displayed with a Cancel button when credential provider is working. I have attached a screenshot of it. I have managed to show the error screen with an Ok button using the following code:

*pcpgsr = CPGSR_NO_CREDENTIAL_NOT_FINISHED; SHStrDupW(L"Authentication Failed", ppwszOptionalStatusText); *pcpsiOptionalStatusIcon = CPSI_ERROR;

Now I need to show this progress screen with a cancel button. Any advice how can it be achieved? Also, how to handle the event that fires when this button is pressed?<a href="https://i.stack.imgur.com/wggOS.png" rel="nofollow"><img alt="This screen should be displayed when credential provider is working" class="b-lazy" data-src="https://i.stack.imgur.com/wggOS.png" data-original="https://i.stack.imgur.com/wggOS.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

Answer1:

As I understand your scenario you want to do something in background presenting to the user "wait screen".

You must run a separate thread for background work and change the layout of your credential tile to leave visible only one text element with "Wait..." content and no submit button.

Once your background thread complete its work you may reveal submit button and let user to continue to logon.

For example, have a look at embedded Smartcard Credential Porvider and its behaviour on insertion and removal of the card.

Answer2:

@js.hrt Per your request.

class Thread { public: Thread(GUI* object); virtual ~Thread(); bool start( bool ) { ::CreateThread( NULL, 0, threadRun, lpParameter, dwCreationFlags, &m_dwThreadId ); } static DWORD WINAPI threadRun( void* lpVoid ) { DWORD dwReturn( 0 ); dwReturn = m_object->yourProcessToRun(); return dwReturn; } protected: GUI* m_object; Runnable* m_lpRunnable;

}; Then, class for your UI, similar to this

#include "atlwin.h" class GUI: public CDialogImpl<GUI> { public: enum { IDD = IDD_FOR_YOUR_DIALOG }; GUI(); ~GUI(); BEGIN_MSG_MAP(GUI) MESSAGE_HANDLER(WM_INITDIALOG,OnInitDialog) COMMAND_ID_HANDLER(ID_CANCEL,OnCancel) MESSAGE_HANDLER(WM_TIMER,OnTimer) MESSAGE_HANDLER(WM_DESTROY,OnDestroy) END_MSG_MAP() LRESULT OnInitDialog(UINT,WPARAM,LPARAM, BOOL&) { myThread = new Thread(this); m_nTimerID = SetTimer(1,3000,NULL); myThread->start(); } LRESULT OnCancel(WORD,WORD,HWND,BOOL& ) { if(NULL != myThread) { DWORD exitCode = 0; myThread->getExitCode(exitCode); if(exitCode == STILL_ACTIVE) myThread->terminate(); delete myThread; myThread = NULL; } EndDialog(IDCANCEL); return true; } LRESULT OnTimer(UINT,WPARAM wParam,LPARAM,BOOL&) { if(wParam != m_nTimerID) return FALSE; m_timerticks++; return FALSE; } LRESULT OnDestroy(UINT,WPARAM,LPARAM,BOOL&) { KillTimer(m_nTimerID); return FALSE; } virtual int yourProcessToRun() {}; void onFinishProgress(int retCode = IDOK) { if (retCode != IDCANCEL) { delete myThread; myThread = NULL; KillTimer(m_nTimerID); EndDialog(retCode); } } private: Thread* myThread; UINT m_nTimerID; UINT m_timerticks;

}; The resource for dialog could be like this:

IDD_FOR_YOUR_DIALOG DIALOGEX 0, 0, 309, 80 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION CAPTION "Whatever" FONT 8, "MS Shell Dlg", 400, 0, 0x0 BEGIN PUSHBUTTON "Cancel",ID_CANCEL,113,50,84,14 CTEXT "Static",IDC_FOR_SOMETHING,7,7,295,20 END

Answer3:

@js.hrt You can run your main thread as dialog, while your background thread does the job. The cancel button would be the control in the dialog, allowing to cancel it. If you need more info, let me know, I can provide some details, as this is the way we do it.

@js.hrt Briefly, you need two classes: dialog and thread. When you create a dialog, it will create a thread, which will run what you need, and show cancel button. Clicking on it will terminate your thread. Some code below. Hope it helps.

class Thread { public: Thread(GUI* object); virtual ~Thread(); bool start( bool ) { ::CreateThread( NULL, 0, threadRun, lpParameter, dwCreationFlags, &m_dwThreadId ); } static DWORD WINAPI threadRun( void* lpVoid ) { DWORD dwReturn( 0 ); dwReturn = m_object->yourProcessToRun(); return dwReturn; } protected: GUI* m_object; Runnable* m_lpRunnable; };

Then, class for your UI, similar to this

#include "atlwin.h" class GUI: public CDialogImpl<GUI> { public: enum { IDD = IDD_FOR_YOUR_DIALOG }; GUI(); ~GUI(); BEGIN_MSG_MAP(GUI) MESSAGE_HANDLER(WM_INITDIALOG,OnInitDialog) COMMAND_ID_HANDLER(ID_CANCEL,OnCancel) MESSAGE_HANDLER(WM_TIMER,OnTimer) MESSAGE_HANDLER(WM_DESTROY,OnDestroy) END_MSG_MAP() LRESULT OnInitDialog(UINT,WPARAM,LPARAM, BOOL&) { myThread = new Thread(this); m_nTimerID = SetTimer(1,3000,NULL); myThread->start(); } LRESULT OnCancel(WORD,WORD,HWND,BOOL& ) { if(NULL != myThread) { DWORD exitCode = 0; myThread->getExitCode(exitCode); if(exitCode == STILL_ACTIVE) myThread->terminate(); delete myThread; myThread = NULL; } EndDialog(IDCANCEL); return true; } LRESULT OnTimer(UINT,WPARAM wParam,LPARAM,BOOL&) { if(wParam != m_nTimerID) return FALSE; m_timerticks++; return FALSE; } LRESULT OnDestroy(UINT,WPARAM,LPARAM,BOOL&) { KillTimer(m_nTimerID); return FALSE; } virtual int yourProcessToRun() {}; void onFinishProgress(int retCode = IDOK) { if (retCode != IDCANCEL) { delete myThread; myThread = NULL; KillTimer(m_nTimerID); EndDialog(retCode); } } private: Thread* myThread; UINT m_nTimerID; UINT m_timerticks; };

The resource for dialog could be like this:

IDD_FOR_YOUR_DIALOG DIALOGEX 0, 0, 309, 80 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION CAPTION "Whatever" FONT 8, "MS Shell Dlg", 400, 0, 0x0 BEGIN PUSHBUTTON "Cancel",ID_CANCEL,113,50,84,14 CTEXT "Static",IDC_FOR_SOMETHING,7,7,295,20 END

@js.hrt If you don't mind to post your code, I'll make it run. Can't comment to your's message directly, as I limit by site requirements

Recommend

  • PC/SC Functions for Digital Signature
  • Initialize a NDEF tag on Windows 10 Desktop
  • Which is more expensive operation swap or comparison in integer array in Java
  • Detection of smart card removal and insertion using PCSC in C
  • MySQL `BEFORE INSERT TRIGGER` how can I skip data insertion under condition? [duplicate]
  • Django - Copying a model instance with 2 nested foreignkeys
  • Sorting Strings in a static array based on their length crashes? |wrong allocation/access|
  • Where to filter Identity 2.0 claim ticket in a WebAPI app?
  • O(1) maintained in hashset lookups when using alternative comparator?
  • Ignoring unknown parameters: point.colour.1
  • postgresql create temp table could block data insertion?
  • MVC HTTPS redirection when behind a load balancer
  • Catch exceptions from RequiredRole and other policies to redirect using Fluent Security
  • replacement of asp:Treeview for ASP.NET MVC application
  • Prove that Excel VBA Scripting.Dictionary does not preserve order of item insertion
  • C++: Why does dereferencing this vector iterator segfault?
  • Set Outlook's 'show this address list first' option
  • php ldap-bind expired password
  • Why the time complexity of an array insertion is O(n) and not O(n+1)? [duplicate]
  • Find 4 minimal values in 4 __m256d registers
  • Office365 authentication without login redirection
  • pure javascript dom dynamic insert, update and delete
  • OAuth2 flow for mobile app
  • Delphi Chromium Embedded - Clear browser cache
  • New-PSSession in an Azure-runbook (ARM)
  • addressing in assembler
  • Encrypting credit card details using AngularJS in Braintree
  • Hibernate in Glassfish - Ejb3Configuration NoClassDefFoundError
  • Cursor in wrong place in contenteditable
  • Spring integration inbound-gateway Fire an event when queue is empty
  • Cloud Code function running twice
  • How to access culture data in globalize.js V1.0.0
  • Ionic 2 storage is not cleaning up on uninstall - Only for signed APK
  • req.body is undefined - nodejs
  • Modifying destination and filename of gulp-svg-sprite
  • Importing jscolor library in angular 2
  • Font Awesome Showing Box instead of Icons
  • jqPlot EnhancedLegendRenderer plugin does not toggle series for Pie charts
  • How can i traverse a binary tree from right to left in java?
  • Conditional In-Line CSS for IE and Others?