Microsoft KB Archive/297111

= How To Read Client Certificate in ASP Component with Visual C++ =

Article ID: 297111

Article Last Modified on 7/2/2004

-

APPLIES TO


 * Microsoft Internet Information Server 4.0
 * Microsoft Internet Information Services 5.0

-



This article was previously published under Q297111



SUMMARY
This article describes how you can read Client Certificates from the Active Server Pages (ASP) Request object by using a component that is written with the Active Template Library (ATL) and with Microsoft Visual C++. Unlike when you read Certificates by means of a script on an ASP page or from a Microsoft Visual Basic component, you must use two interfaces implemented by ASP to use this functionality. These interfaces are (in order of use):
 * IResponse
 * IRequestDictionary

The functional flow of Client Certificate from a Visual C++ component follows:


 * 1) Obtain the Response object from the IScriptingContext or the IObjectContext.
 * 2) Use the Response object to obtain an IRequestDictionary interface that contains the Client Certificate collection.
 * 3) Get the &quot;Certificate&quot; item from the collection.
 * 4) Obtain a default member (value property) from the IDispatch interface returned in the earlier step.



MORE INFORMATION

 * 1) Create a new Visual C++ 6.0 project by using the ATL COM AppWizard.
 * 2) From the list of available server types, make sure DLL is selected, and then click Finish.
 * 3) On the Insert menu, click New ATL Object.
 * 4) From the Objects category, click ActiveX Server Component.

After you have a Component Object Model (COM) object, add a method that obtains a Client Certificate, and then save the Client Certificate to the file. You can use code similar to the following code sample: STDMETHODIMP CComClass::GetCert(BSTR* szCert) {

TCHAR szTemp [256]; CComPtr piCert; CComVariant vt(L&quot;Certificate&quot;), vtRet;

*szCert = NULL;

HRESULT hr = m_piRequest->get_ClientCertificate (&piCert); if (FAILED(hr)) {   ATLTRACE (szTemp, L&quot;get_ClientCertificate failed: 0x%x\n&quot;, hr); return hr; }   hr = piCert->get_Item (vt, &vtRet); if (FAILED(hr)) {   ATLTRACE (szTemp, L&quot;get_Item failed: 0x%x\n&quot;, hr); return hr; }   if(vtRet.vt == VT_DISPATCH) {          DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; CComVariant VarResult; CComPtr  pDisp (vtRet.pdispVal); hr = pDisp->Invoke(DISPID_VALUE, IID_NULL, LOCALE_USER_DEFAULT,              DISPATCH_METHOD, &dispparamsNoArgs, &VarResult,                           NULL, NULL); if (FAILED(hr)) {       ATLTRACE (szTemp, L&quot;Invoke failed: 0x%x\n&quot;, hr); return hr; }   DWORD dwSize = SysStringLen (VarResult.bstrVal); CHAR *szCertANSI= new CHAR [dwSize]; if (!WideCharToMultiByte (CP_ACP, 0, VarResult.bstrVal, dwSize, szCertANSI, dwSize, NULL, NULL)) {             DWORD dwError = GetLastError; ATLTRACE (szTemp, L&quot;Conversion failed: 0x%x\n&quot;,                                    dwError); delete [] szCertANSI; return HRESULT_FROM_WIN32 (dwError); }   ofstream myFile (&quot;c:\\temp\\Cert.cer&quot;, ios::binary   ); myFile.write ((char*)szCertANSI, dwSize); myFile.close;

delete [] szCertANSI; *szCert = SysAllocString (L&quot;File with Cert is saved!&quot;); return S_OK; }      return E_INVALIDARG; }

NOTE: The m_piRequest is a pointer to ASP intrinsics interface IRequest, which is available to your component. See the platform software development kit (SDK) documentation for information about how you can obtain a pointer to IRequest in the component.

You can use the following ASP code to test the COM object:

<% Dim myObj

Set myObj = Server.CreateObject (&quot;AspCom.ComClass&quot;) Response.Write myObj.GetCert %> NOTE: You must make sure to use the correct ProgId property in the CreateObject function so that the CreateObject reflects the correct name of your component.

