CertSelectCertificate hook Callback Function does not get called

I am trying to use a callback function in order to center the certificate window, but it can't seem to get it to work.

I have set the pfnHook pointer with
certSelect.pfnHook = (PFNCMHOOKPROC)&CertHookCallback;

I have  set the flag saying that a hook function should be called using:      
certSelect.dwFlags = CSS_ENABLEHOOK;

The selectCert dialog is displayed but it does not hit my breakpoint in the callback function nor does it print, so i assume it is never reached. What have i missed?
static UINT_PTR CALLBACK CertHookCallback( 
	HWND hDlg,
	UINT uiMsg,
	WPARAM wParam,
	LPARAM lParam)
{
          Trace(TRC_LOGIC, ("Callback function reached.\n"));
	if ( uiMsg == WM_SIZE) {

            // Center window and bring it to front
            Center(hdlg); 

         }
}

GetCert()
{
CERT_SELECT_STRUCT certSelect;
	PCCERT_CONTEXT pSelCert = NULL;
	// set cert dialog data and call function

	memset(&certSelect, 0, sizeof(CERT_SELECT_STRUCT));

	DLGTEMPLATE dlgTemplate;

	dlgTemplate.x = 0;
	dlgTemplate.y = 0;
	//certSelect.pTemplateName =&dlgTemplate;

	certSelect.dwFlags = CSS_ENABLEHOOK;
	certSelect.dwSize = sizeof(CERT_SELECT_STRUCT);
	certSelect.hwndParent = GetForegroundWindow();
	certSelect.pfnHook = (PFNCMHOOKPROC)&CertHookCallback;
	certSelect.cCertStore = 1;  
	certSelect.arrayCertStore = &hTmpStore;
	certSelect.cCertContext = 1;  
	certSelect.arrayCertContext = &pSelCert;


	DWORD rc = pCertSelectCertificate(&certSelect);


}

Open in new window

endasilAsked:
Who is Participating?
 
DanRollinsCommented:
Using code from Sign.CPP (a sample file in the SDK), I was able to reproduce the problem.  However, the return code was 1 (true)  -- I was able to select a cert, but the hook did not get called.
There is a possble clue:  
Note that the docs refer you to "See Hooks" which is at
    http://msdn.microsoft.com/en-us/library/ms632589(VS.85).aspx
and is all about Windows Hooks... which seems odd to me.  This is really a callback, not a hook, per se.
However, one item in there might apply.  Note that in SetWindowsHookEx http://msdn.microsoft.com/en-us/library/ms644990(VS.85).aspx  the docs now say that you need 64-bit hook code to inject into a 64-bit process.  Like I say, it does not seem like it should apply, but it might.
Are you having this problem on a Win7 or Vista 64-bit machine?
====================
If you can't fix this, then a possible workaround would be to spin-off a thread that would watch for the dialog to appear then move it.  See Simple Multithreading in Visual C++
0
 
jkrCommented:
Stupid question - does that work with

certSelect.pfnHook = (PFNCMHOOKPROC) CertHookCallback;

instead? Also, according to the docs (http://msdn.microsoft.com/en-us/library/aa387047%28VS.85%29.aspx - "PFNCMHOOKPROC Callback Function"), the callback should be more like
UINT WINAPI CertHookCallback( 
        HWND hDlg,
        UINT uiMsg,
        WPARAM wParam,
        LPARAM lParam)
{
          Trace(TRC_LOGIC, ("Callback function reached.\n"));
        if ( uiMsg == WM_SIZE) {

            // Center window and bring it to front
            Center(hdlg); 

         }

  return 0;
}

Open in new window

0
 
endasilAuthor Commented:
I tried making the changes you suggested but it still does not get called. Here is a small program that only contains whats needed to run the dialog example with your suggestions included.
#include <windows.h>
#include <wincrypt.h>
#include <stdlib.h>
#include "C:\Program\Microsoft SDKs\Windows\v6.0A\include\cryptdlg.h"


UINT WINAPI CertHookCallback(HWND hDlg,
							 UINT uiMsg,
							 WPARAM wParam,
							 LPARAM lParam)
{	
	if ( uiMsg == WM_SIZE) { 
		exit(0);
	}
	return NULL;
}

int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd)
{
	HMODULE hLib = LoadLibrary(L"cryptdlg.dll");;	
	HCERTSTORE hTmpStore = CertOpenStore(CERT_STORE_PROV_MEMORY, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0, NULL);	
	BOOL (WINAPI *pCertSelectCertificate)(PCERT_SELECT_STRUCT) = NULL;		
	pCertSelectCertificate = (BOOL (WINAPI *)(PCERT_SELECT_STRUCT))GetProcAddress(hLib, "CertSelectCertificateW");	
	
	CERT_SELECT_STRUCT certSelect;
	PCCERT_CONTEXT pSelCert = NULL;
	
	memset(&certSelect, 0, sizeof(CERT_SELECT_STRUCT));
	certSelect.dwFlags = CSS_ENABLEHOOK;
	certSelect.dwSize = sizeof(CERT_SELECT_STRUCT);
	certSelect.hwndParent = GetForegroundWindow();
	certSelect.pfnHook = (PFNCMHOOKPROC)CertHookCallback;
	certSelect.cCertStore = 1;  
	certSelect.arrayCertStore = &hTmpStore;
	certSelect.cCertContext = 1;  
	certSelect.arrayCertContext = &pSelCert;
	DWORD rc = pCertSelectCertificate(&certSelect);

	return 0;
}

Open in new window

0
Simple Misconfiguration =Network Vulnerability

In this technical webinar, AlgoSec will present several examples of common misconfigurations; including a basic device change, business application connectivity changes, and data center migrations. Learn best practices to protect your business from attack.

 
jkrCommented:
What is the return value in

DWORD rc = pCertSelectCertificate(&certSelect);

?
0
 
endasilAuthor Commented:
It returns 0, and GetLastError returns 0 as well.
0
 
endasilAuthor Commented:
Thank you for your reply and taking your time to try to help me out here. Much appriciated. I have now tested my code on windows xp, visa as well as 7, all of them 32bit OS, but i have the same problem on all of them. So i guess it is not related to be related to 64bit.

I guess whats left is your spin-off thread idea. I had no idea you could find the hwnd of a dialog that exist on the screen, how would i go about to archive that?
0
 
endasilAuthor Commented:
The only function that i have found that can do something like this is FindWindow, that lets you find a window by the title. But this does not seem to be a reliable idea if the application is going to be used in multiple languages.
0
 
DanRollinsCommented:
In such cases. You can use Spy++ to see if you can find anything that's unique about the window.  On my Win7 system, I see that the caption is "Windows Security" with a classname of  "#32770 (Dialog)" It's first child has a classname of "DirectUIHWND"  The "owning process" is my "certtest.exe" app.  The parent window is the one that I specified in the call to CertSelectCertificate.  etc.
 
0
 
endasilAuthor Commented:
Thanks, got it working with the thread method. Complete source for anyone else who runs into this problem:


#include <afxwin.h>
#include <windows.h>
#include <wincrypt.h> 
#include <stdlib.h> 
#include <vector>
#include "C:\Program\Microsoft SDKs\Windows\v6.0A\include\cryptdlg.h" 
#define DIALOG_CLASS _T("#32770")

UINT WINAPI CertHookCallback(HWND hDlg, 
							 UINT uiMsg, 
							 WPARAM wParam, 
							 LPARAM lParam) 
{        
	exit(0);
	if ( uiMsg == WM_SIZE) {  
		exit(0); 
	} 
	return NULL; 
} 

bool g_run = true;


DWORD threadDlg = 0;
DWORD idapp = 0;
DWORD currThread = 0;
bool dialogFound = 0;

void CenterWindow(HWND hwnd)
{
	RECT    rect;
	LONG    dx, dy;
	LONG    dxParent, dyParent;
	LONG    Style;

	// Get window rect
	GetWindowRect(hwnd, &rect);

	dx = rect.right - rect.left;
	dy = rect.bottom - rect.top;

	// Get parent rect
	Style = GetWindowLong(hwnd, GWL_STYLE);
	if ((Style & WS_CHILD) == 0) {

		// Return the desktop windows size (size of main screen)
		dxParent = GetSystemMetrics(SM_CXSCREEN);
		dyParent = GetSystemMetrics(SM_CYSCREEN);
	} else {
		HWND    hwndParent;
		RECT    rectParent;

		hwndParent = GetParent(hwnd);
		if (hwndParent == NULL) {
			hwndParent = GetDesktopWindow();
		}

		GetWindowRect(hwndParent, &rectParent);

		dxParent = rectParent.right - rectParent.left;
		dyParent = rectParent.bottom - rectParent.top;
	}

	// Centre the child in the parent
	rect.left = (dxParent - dx) / 2;
	rect.top  = (dyParent - dy) / 3;

	// Move the child into position
	SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, 0, 0, SWP_NOSIZE);

}

BOOL CALLBACK FindDialog(HWND hwnd, LPARAM lparam)
{
	TCHAR name[MAX_PATH];
	ZeroMemory(name, sizeof(name));

	GetClassName(hwnd, name, MAX_PATH);

	// See if this is a dialog window
	if(_tcscmp(name, DIALOG_CLASS) == 0){						
		
		// Check if this app is the creator of the window.
		DWORD idOfCreator = 0;
		GetWindowThreadProcessId(hwnd,&idOfCreator);
		if(idOfCreator == lparam)
		{
			CenterWindow(hwnd);
			g_run = false;		
		}
	}
	// Return value is used by EnumWindows to know when to stop.	
	return g_run;

}


UINT MonitorCertWindow(LPVOID pParam)
{
	// Enumerate windows until the select certificate window is found	
	while(g_run == true)
	{
		EnumWindows(FindDialog, GetCurrentProcessId());
	}

	return 0;
}

int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd) 
{ 
	

	HMODULE hLib = LoadLibrary(L"cryptdlg.dll");;    
	HCERTSTORE hTmpStore = CertOpenStore(CERT_STORE_PROV_MEMORY, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0, NULL);       
	BOOL (WINAPI *pCertSelectCertificate)(PCERT_SELECT_STRUCT) = NULL;               
	pCertSelectCertificate = (BOOL (WINAPI *)(PCERT_SELECT_STRUCT))GetProcAddress(hLib, "CertSelectCertificateW");   

	CERT_SELECT_STRUCT certSelect; 
	PCCERT_CONTEXT pSelCert = NULL; 
	
	AfxBeginThread(MonitorCertWindow, 0);
	memset(&certSelect, 0, sizeof(CERT_SELECT_STRUCT)); 
	certSelect.dwFlags = CSS_ENABLEHOOK; 
	certSelect.dwSize = sizeof(CERT_SELECT_STRUCT); 
	certSelect.hwndParent = GetForegroundWindow(); 
	certSelect.pfnHook = (PFNCMHOOKPROC)&CertHookCallback; 
	certSelect.cCertStore = 1;   
	certSelect.arrayCertStore = &hTmpStore; 
	certSelect.cCertContext = 1;   
	certSelect.arrayCertContext = &pSelCert; 
	

	DWORD rc = pCertSelectCertificate(&certSelect); 
	
	return 0; 
}

Open in new window

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.