|
Hi all
I've built a sample code named "enrollCustomCMC" in Windows SDK at "Microsoft SDKs\Windows\v6.1\Samples\Security\X509 Certificate Enrollment\VC" directory, but when the ".exe" file is built and I use it with the "Command Prompt", I see error in first "CoCreateInstance" function as "REGDB_E_CLASSNOTREG" that means: "Class not registered"!
I couldn't find the reason even with debugging!
The code is written using COM interface, here's the code:
#include <stdio.h>
#include <certenroll.h>
#include <certsrv.h>
#include <certcli.h>
#include <wincrypt.h>
#include "enrollCommon.h"
void Usage()
{
wprintf(L"Usage:\n");
wprintf(L"enrollCustomCMC <name> <value> <dns> <eku> \n");
wprintf(L"Example: enrollCustomCMC Name Value ");
wprintf(L"www.adatum.com 1.3.6.1.5.5.7.3.1\n");
}
HRESULT __cdecl wmain(__in int argc, __in_ecount(argc) wchar_t *argv[])
{
HRESULT hr = S_OK;
bool fCoInit = false;
ICertRequest2* pCertRequest2 = NULL;
ICertConfig* pCertConfig = NULL;
IX509Enrollment* pEnroll = NULL;
IX509CertificateRequest* pRequest = NULL;
IX509CertificateRequestPkcs10* pPkcs10 = NULL;
IX509CertificateRequestCmc* pCmc = NULL;
IX509Extensions* pExtensions = NULL;
IX509Extension* pExtension1 = NULL;
IX509Extension* pExtension2 = NULL;
IX509ExtensionEnhancedKeyUsage* pExtensionEKU = NULL;
IX509ExtensionAlternativeNames* pExtensionSAN = NULL;
IObjectId *pEKUObjectId = NULL;
IObjectId *pSANObjectId = NULL;
IObjectIds *pEKUObjectIds = NULL;
IObjectIds *pSANObjectIds = NULL;
IAlternativeName * anDnsName = NULL;
IAlternativeNames * pAlternativeNames = NULL;
IX509NameValuePair *pPair = NULL;
IX509NameValuePairs *pPairs = NULL;
PCWSTR pwszName;
PCWSTR pwszValue;
PCWSTR pwszDnsName;
PCWSTR pwszEKU;
BSTR strCAConfig = NULL;
BSTR strDnsName = NULL;
BSTR strName = NULL;
BSTR strValue = NULL;
BSTR strEKU = NULL;
BSTR strRequest = NULL;
BSTR strCert = NULL;
BSTR strDisposition = NULL;
LONG pDisposition = 0;
// Process command line arguments
if (argc != 5) {
Usage();
hr = E_INVALIDARG;
_JumpError(hr, error, "invalid arg");
}
else
{
pwszName = argv[1];
pwszValue = argv[2];
pwszDnsName = argv[3];
pwszEKU = argv[4];
}
// CoInitializeEx
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
_JumpIfError(hr, error, "CoInitializeEx");
fCoInit = true;
// Create IX509CertificateRequestPkcs10
hr = CoCreateInstance(
__uuidof(CX509CertificateRequestPkcs10),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IX509CertificateRequestPkcs10),
(void **) &pPkcs10);
_JumpIfError(hr, error, "CoCreateInstance");
// Initialize IX509CertificateRequestPkcs10
hr = pPkcs10->Initialize(ContextMachine);
_JumpIfError(hr, error, "Initialize");
// Create IX509CertificateRequestCmc
hr = CoCreateInstance(
__uuidof(CX509CertificateRequestCmc),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IX509CertificateRequestCmc),
(void **) &pCmc);
_JumpIfError(hr, error, "CoCreateInstance");
// Initialize CMC request
hr = pCmc->InitializeFromInnerRequest(pPkcs10);
_JumpIfError(hr, error, "InitializeFromInnerRequest");
/* Create EKU extention from an OID */
// Create IObjectId
hr = CoCreateInstance(
__uuidof(CObjectId),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IObjectId),
(void **) &pEKUObjectId);
_JumpIfError(hr, error, "CoCreateInstance");
// Allocate BSTR for EKU OID
strEKU = SysAllocString(pwszEKU);
if (NULL == strEKU)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "SysAllocString");
}
// Initialize IObjectId from EKU OID
hr = pEKUObjectId->InitializeFromValue(strEKU);
_JumpIfError(hr, error, "InitializeFromValue");
// Create IObjectIds
hr = CoCreateInstance(
__uuidof(CObjectIds),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IObjectIds),
(void **) &pEKUObjectIds);
_JumpIfError(hr, error, "CoCreateInstance");
// Add IObjectId into IObjectIds collection
hr = pEKUObjectIds->Add(pEKUObjectId);
_JumpIfError(hr, error, "Add");
// Create IX509ExtensionEnhancedKeyUsage
hr = CoCreateInstance(
__uuidof(CX509ExtensionEnhancedKeyUsage),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IX509ExtensionEnhancedKeyUsage),
(void **) &pExtensionEKU);
_JumpIfError(hr, error, "CoCreateInstance");
// Initialize IX509ExtensionEnhancedKeyUsage from IObjectIds
hr = pExtensionEKU->InitializeEncode(pEKUObjectIds);
_JumpIfError(hr, error, "InitializeEncode");
// QueryInterface of IX509Extension
hr = pExtensionEKU->QueryInterface(
__uuidof(IX509Extension),
(VOID **)&pExtension1);
_JumpIfError(hr, error, "QueryInterface");
/* Create SAN extention from a DNS Name */
// Create IAlternativeName
hr = CoCreateInstance(
__uuidof(CAlternativeName),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IAlternativeName),
(void **) &anDnsName);
_JumpIfError(hr, error, "CoCreateInstance");
// Allocate BSTR for DNS name
strDnsName = SysAllocString(pwszDnsName);
if (NULL == strDnsName)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "SysAllocString");
}
// Initialize IAlternativeName
hr = anDnsName->InitializeFromString(
XCN_CERT_ALT_NAME_DNS_NAME,
strDnsName);
_JumpIfError(hr, error, "InitializeFromString");
// Create IAlternativeNames
hr = CoCreateInstance(
__uuidof(CAlternativeNames),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IAlternativeNames),
(void **) &pAlternativeNames);
_JumpIfError(hr, error, "CoCreateInstance");
// Add IAlternativeName into IAlternativeNames collection
hr = pAlternativeNames->Add(anDnsName);
_JumpIfError(hr, error, "Add");
// Create IX509ExtensionAlternativeNames
hr = CoCreateInstance(
__uuidof(CX509ExtensionAlternativeNames),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IX509ExtensionAlternativeNames),
(void **) &pExtensionSAN);
_JumpIfError(hr, error, "CoCreateInstance");
// Initialize IX509ExtensionAlternativeNames
hr = pExtensionSAN->InitializeEncode(pAlternativeNames);
_JumpIfError(hr, error, "InitializeEncode");
// QueryInterface of IX509Extension
hr = pExtensionSAN->QueryInterface(
__uuidof(IX509Extension),
(VOID **)&pExtension2);
_JumpIfError(hr, error, "QueryInterface");
/* Add EKU and SAN extension into CMC request */
// Get extensions from the CMC request
hr = pCmc->get_X509Extensions(&pExtensions);
_JumpIfError(hr, error, "get_X509Extensions");
// Add EKU extension into the request
hr = pExtensions->Add(pExtension1);
_JumpIfError(hr, error, "Add");
// Add SAN extension into the request
hr = pExtensions->Add(pExtension2);
_JumpIfError(hr, error, "Add");
/* Create name value pair and add it into CMC request */
// Create IX509NameValuePair
hr = CoCreateInstance(
__uuidof(CX509NameValuePair),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IX509NameValuePair),
(void **) &pPair);
_JumpIfError(hr, error, "CoCreateInstance");
// Allocate BSTR for name
strName = SysAllocString(pwszName);
if (NULL == strName)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "SysAllocString");
}
// Allocate BSTR for value
strValue = SysAllocString(pwszValue);
if (NULL == strValue)
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "SysAllocString");
}
// Initialize IX509NameValuePair
hr = pPair->Initialize(strName, strValue);
_JumpIfError(hr, error, "Initialize");
// Get IX509NameValuePairs from CMC request
hr = pCmc->get_NameValuePairs(&pPairs);
_JumpIfError(hr, error, "get_NameValuePairs");
// Add IX509NameValuePair into IX509NameValuePairs collection
hr = pPairs->Add(pPair);
_JumpIfError(hr, error, "Add");
/* Create enrollment request */
// Create IX509Enrollment
hr = CoCreateInstance(
__uuidof(CX509Enrollment),
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
__uuidof(IX509Enrollment),
(void **) &pEnroll);
_JumpIfError(hr, error, "CoCreateInstance");
// Initialize IX509Enrollment from CMC request
hr = pEnroll->InitializeFromRequest(pCmc);
_JumpIfError(hr, error, "InitializeFromRequest");
// Create request
hr = pEnroll->CreateRequest(
XCN_CRYPT_STRING_BASE64,
&strRequest);
_JumpIfError(hr, error, "CreateRequest");
/* Submit request to SA CA, get response and install it */
// Create ICertConfig
hr = CoCreateInstance(
__uuidof(CCertConfig),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(ICertConfig),
(void**)&pCertConfig);
_JumpIfError(hr, error, "CoCreateInstance");
// Get the CA Config from UI
hr = pCertConfig->GetConfig(CC_UIPICKCONFIG, &strCAConfig);
_JumpIfError(hr, error, "GetConfig");
// Create ICertRequest2
hr = CoCreateInstance(
__uuidof(CCertRequest),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(ICertRequest2),
(void**)&pCertRequest2);
_JumpIfError(hr, error, "CoCreateInstance");
// Submit the request
hr = pCertRequest2->Submit(
CR_IN_BASE64 | CR_IN_FORMATANY,
strRequest,
NULL,
strCAConfig,
&pDisposition);
_JumpIfError(hr, error, "Submit");
// Check the submission status
if (pDisposition != CR_DISP_ISSUED) // Not enrolled
{
hr = pCertRequest2->GetDispositionMessage(&strDisposition);
_JumpIfError(hr, error, "GetDispositionMessage");
if (pDisposition == CR_DISP_UNDER_SUBMISSION) // Pending
{
wprintf(L"The submission is pending: %ws\n", strDisposition);
_JumpError(hr, error, "Submit");
}
else // Failed
{
wprintf(L"The submission failed: %ws\n", strDisposition);
pCertRequest2->GetLastStatus(&hr);
_JumpError(hr, error, "Submit");
}
}
// Get the certifcate
hr = pCertRequest2->GetCertificate(
CR_OUT_BASE64 | CR_OUT_CHAIN,
&strCert);
_JumpIfError(hr, error, "GetCertificate");
// Install the certifcate
hr = pEnroll->InstallResponse(
AllowNone,
strCert,
XCN_CRYPT_STRING_BASE64,
NULL);
_JumpIfError(hr, error, "InstallResponse");
error:
SysFreeString(strCAConfig);
SysFreeString(strDnsName);
SysFreeString(strName);
SysFreeString(strValue);
SysFreeString(strEKU);
SysFreeString(strRequest);
SysFreeString(strCert);
SysFreeString(strDisposition);
if (NULL != pCertRequest2) pCertRequest2->Release();
if (NULL != pCertConfig) pCertConfig->Release();
if (NULL != pEnroll) pEnroll->Release();
if (NULL != pRequest) pRequest->Release();
if (NULL != pPkcs10) pPkcs10->Release();
if (NULL != pCmc) pCmc->Release();
if (NULL != pExtensions) pExtensions->Release();
if (NULL != pExtension1) pExtension1->Release();
if (NULL != pExtension2) pExtension2->Release();
if (NULL != pExtensionEKU) pExtensionEKU->Release();
if (NULL != pExtensionSAN) pExtensionSAN->Release();
if (NULL != pEKUObjectId) pEKUObjectId->Release();
if (NULL != pSANObjectId) pSANObjectId->Release();
if (NULL != pEKUObjectIds) pEKUObjectIds->Release();
if (NULL != pSANObjectIds) pSANObjectIds->Release();
if (NULL != anDnsName) anDnsName->Release();
if (NULL != pAlternativeNames) pAlternativeNames->Release();
if (NULL != pPair) pPair->Release();
if (NULL != pPairs) pPairs->Release();
if (fCoInit) CoUninitialize();
return hr;
}
What's the problem?
And does this code need to a CA(certification Authority) to send request for?
Is it possible to run this code on XP client than Vista?
I asked this question on "Windows SDK" forum, but didn't get any respose!!
Please help me...
THX.
|
|
|
|
|
What are the setup instructions for the sample?
Are the COM classes registered using regsvr32.exe?
|
|
|
|
|
The documentation clearly states that these API's are available starting with Windows Vista. So no XP
|
|
|
|
|
I have no clue how to pass data to my threaded function.
_beginthread(MyThreadFunction, 0, NULL);
Tried to pass a value like in regular C++ functions.
_beginthread(MyThreadFunction(MyData), 0, NULL);
Kept getting compile errors!
|
|
|
|
|
Arguments to threads are usually passed as void pointers (void*).
So you need to pass in what ever is needed by typecasting it to a void*.
So if you want to pass an integer -
int i = 10;
_beginthread(MyThreadFunction, 0, (void*)&i);
|
|
|
|
|
How would the thread function declaration look like?
|
|
|
|
|
|
_beginthread(DownloadThread, 0, (void*) NewDownload);
void DownloadThread(void *D)
{
CDownload *Download = (CDownload*)D;
}
Compiles, but once the _beginthread is called the program crashes!
modified on Monday, April 26, 2010 3:39 PM
|
|
|
|
|
How is NewDownload declared?
|
|
|
|
|
1) Window that accepts URL
2) Pressing OK
3) Break down URL store it in CDownload *NewDownload;
4) After NewDownload has been filled out.
5) I pass NewDownload to download function to test if it the download function works
6) Add NewDownload to Linked List
Production code, user will be able to pause/resume called the download thread
|
|
|
|
|
Declaration, not implementation or use. In other words, is NewDownload a CDownload object?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
|
It seems passing Class Object part of a Linked List doesn't not work in this traditional manner!
|
|
|
|
|
Try something like this -
CDownload* NewDownload = new CDownload;
_beginthread(MyThreadFunction, 0, (void*)NewDownload);
|
|
|
|
|
How would the MyThreadFunction declaration look like?
void MyThreadFuction (void* Download)
{
char *HostName = new char[wcslen(Download->HostName)+1];
}
error C2227: left of '->HostName' must point to class/struct/union/generic type
|
|
|
|
|
void MyThreadFuction (void* Download)
{
CDownload* NewDownload = (CDownload*)Download;
char *HostName = new char[wcslen(NewDownload->HostName)+1];
}
|
|
|
|
|
Thank You for your patience.
Actually I had done that same workaround fix, but since of my inexperience I thought I was doing it wrong.
As it appears I found another reason causing the disruption which has caused all this fuss.
Since I'm using long long, doing a percentage calculation. However because of 0 being part of my calculation. It crashes! Bringing up lldiv.asm to Line 121 due to the 0 value. Anyway I will try understand went wrong later. Thanks again for your help Nameless MVP!
|
|
|
|
|
I briefly talk about this here.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
I remember reading that - a great piece of code (not that you need me to tell you)
I'm sure someone was asking about printer notifications recently here on CP as well, so your article was timely.
'g'
|
|
|
|
|
<pre>_beginthread(MyThreadFunction, 0, NULL);
Tried to pass a value like in regular C++ functions.
_beginthread(MyThreadFunction(MyData), 0, NULL);</pre>
look at how you call _beginthread and combine what the other people have already posted. You have the idea, but just look at how _beginthread is defined.
~ELChupathingy
|
|
|
|
|
Here's a nice writeup[^] on the subject. He emphasises on MFC, but the idea is the same.
A book on threading would be of immense help to you.
“Follow your bliss.” – Joseph Campbell
|
|
|
|
|
So in a normal C++ environment you can use fstream!
CFile in MFC applications, does anyone know of other file writing functions that don't involve MFC.
While also restricting output with number of bytes to write?
|
|
|
|
|
Fareed Rizkalla wrote: does anyone know of other file writing functions that don't involve MFC.
How about WriteFile() and fprintf() ?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
You could start here[^] and work your way up. The basic IO functions require you to do all the work, in terms of formatting your data.
It's time for a new signature.
|
|
|
|
|
I have a lot of legacy code using fprintf(stderr, .....); I also have monitoring pane which is a CEdit control. How can I redirect stderr to output into the CEdit control?
I have a look around but most of the answers involve the creation of a new process. Is any simpler way of doing it? Effectively what I 'd like to do is something like
start redirection of stderr to myEditControl;
fprintf(stder, ....);
finish redirection of stderr
Thanks
|
|
|
|
|