• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1169
  • Last Modified:

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

0
endasil
Asked:
endasil
  • 5
  • 2
  • 2
2 Solutions
 
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
 
jkrCommented:
What is the return value in

DWORD rc = pCertSelectCertificate(&certSelect);

?
0
NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

 
endasilAuthor Commented:
It returns 0, and GetLastError returns 0 as well.
0
 
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
 
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

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 5
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now