title: Microsoft C++ HTTP Server API (httpapi.lib) HttpReceiveClientCertificate function Return ERROR_NOT_FOUND ( 1168 )
body: <p>Microsoft C++ HTTP Server API (httpapi.lib) for HTTPS</p>
  
  <p>I want create https server in c++ by Microsoft http server api
  <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364510(v=vs.85).aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/windows/desktop/aa364510(v=vs.85).aspx</a></p>
  
  <p>i following these steps that are mentioned below</p>
  
  <p><a href="http://www.codeproject.com/Articles/24027/SSL-with-Self-hosted-WCF-Service?msg=3930582#xx3930582xx" rel="nofollow">http://www.codeproject.com/Articles/24027/SSL-with-Self-hosted-WCF-Service?msg=3930582#xx3930582xx</a></p>
  
  <ol>
  <li>makecert -sv SignRoot.pvk -cy authority -r signroot.cer -a sha1 -n "CN=Dev Certification Authority" -ss my -sr localmachine</li>
  </ol>
  
  <p>Succeeded</p>
  
  <ol>
  <li>makecert -iv SignRoot.pvk -ic signroot.cer -cy end -pe -n CN="localhost" -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localmachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12</li>
  </ol>
  
  <p>Succeeded</p>
  
  <ol>
  <li>config https according
  <a href="http://msdn.microsoft.com/en-us/library/ms733791.aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/ms733791.aspx</a></li>
  </ol>
  
  <p>netsh http add sslcert ipport=127.0.0.1:4443 certhash=9eb4919ea794d783a348a0469474c4cf45d65fb3 appid={F8C3E640-D91E-11D2-9944-8F3C3FD5C32F} sslctlstorename=MY clientcertnegotiation=enable</p>
  
  <p>SSL Certificate successfully added</p>
  
  <p>Result :</p>
  
  <blockquote>
  <pre><code>IP:port                 : 127.0.0.1:4443
  Certificate Hash        : 9eb4919ea794d783a348a0469474c4cf45d65fb3
  Application ID          : {f8c3e640-d91e-11d2-9944-8f3c3fd5c32f} 
  Certificate Store Name  : (null) 
  Verify Client Certificate Revocation    : Enabled
  Verify Revocation Using Cached Client Certificate Only    : Disabled
  Usage Check    : Enabled
  Revocation Freshness Time : 0 
  URL Retrieval Timeout   : 0 
  Ctl Identifier          : (null) 
  Ctl Store Name          : MY 
  DS Mapper Usage    : Disabled
  Negotiate Client Certificate    : Enabled
  </code></pre>
  </blockquote>
  
  <p>This is complete sample code</p>
  
  <pre><code>#include "stdafx.h"
  #include &lt;stdio.h&gt;
  #include &lt;iostream&gt;
  #include &lt;cstdlib&gt;
  #include &lt;conio.h&gt;
  #include &lt;iostream&gt; 
  #include &lt;tchar.h&gt;
  
  using namespace std;
  
  #ifndef _WIN32_WINNT
  #define _WIN32_WINNT 0x0600
  #endif
  
  #ifndef WIN32_LEAN_AND_MEAN
  #define WIN32_LEAN_AND_MEAN
  #endif
  
  #include &lt;http.h&gt;
  #pragma comment(lib, "httpapi.lib")
  
  //
  // Macros.
  //
  #define INITIALIZE_HTTP_RESPONSE( resp, status, reason )    \
  do                                                      \
  {                                                       \
      RtlZeroMemory( (resp), sizeof(*(resp)) );           \
      (resp)-&gt;StatusCode = (status);                      \
      (resp)-&gt;pReason = (reason);                         \
      (resp)-&gt;ReasonLength = (USHORT) strlen(reason);     \
  } while (FALSE)
  
  #define ADD_KNOWN_HEADER(Response, HeaderId, RawValue)               \
  do                                                               \
  {                                                                \
      (Response).Headers.KnownHeaders[(HeaderId)].pRawValue =      \
                                                        (RawValue);\
      (Response).Headers.KnownHeaders[(HeaderId)].RawValueLength = \
          (USHORT) strlen(RawValue);                               \
  } while(FALSE)
  
  #define ALLOC_MEM(cb) HeapAlloc(GetProcessHeap(), 0, (cb))
  
  #define FREE_MEM(ptr) HeapFree(GetProcessHeap(), 0, (ptr))
  
  //
  // Prototypes.
  //
  DWORD DoReceiveRequests(HANDLE hReqQueue);
  
  DWORD SendHttpResponse(HANDLE hReqQueue, PHTTP_REQUEST pRequest, USHORT StatusCode, PSTR pReason, PSTR pEntity);
  
  DWORD SendHttpPostResponse(HANDLE hReqQueue, PHTTP_REQUEST pRequest);
  
  /*******************************************************************/
  
  int __cdecl wmain(int argc, wchar_t * argv[])
  {   
      HTTPAPI_VERSION HttpApiVersion = HTTPAPI_VERSION_1;
  
      ULONG ret = NO_ERROR;
      HRESULT hr = S_OK;
      HTTPAPI_VERSION ver = HTTPAPI_VERSION_1;
  
      ret = HttpInitialize(ver,HTTP_INITIALIZE_SERVER|HTTP_INITIALIZE_CONFIG,NULL);
      if(ret!=NO_ERROR)
          return 0;
  
  
      ULONG           retCode;
      HANDLE          hReqQueue      = NULL;  //request queue handle
      int             UrlAdded       = 0;
  
      retCode = HttpInitialize( 
                  HttpApiVersion,
                  HTTP_INITIALIZE_SERVER ,
                  NULL                     
                  );
  
      if (retCode == NO_ERROR)
      {  
          retCode = HttpCreateHttpHandle(&amp;hReqQueue,// Req Queue
                      0                  // Reserved
                      );   
          if (retCode == NO_ERROR)
          {    
               retCode = HttpAddUrl(
                              hReqQueue,    // Req Queue
                              L"https://127.0.0.1:4443/",// Fully qualified URL
                              NULL          // Reserved
                              );
              if (retCode == NO_ERROR)
              {            
                DoReceiveRequests(hReqQueue);
              }      
          }
      }            
      return retCode;
  }//main
  
  
  /*******************************************************************++
  
  Routine Description:
  The function to receive a request. This function calls the  
  corresponding function to handle the response.
  
  Arguments:
  hReqQueue - Handle to the request queue
  
  Return Value:
  Success/Failure.
  
  --*******************************************************************/
  DWORD DoReceiveRequests(IN HANDLE hReqQueue)
  {
  ULONG              result;
  HTTP_REQUEST_ID    requestId;
  DWORD              bytesRead;
  PHTTP_REQUEST      pRequest;
  PCHAR              pRequestBuffer;
  ULONG              RequestBufferLength;
  
  //
  // Allocate a 2 KB buffer. This size should work for most 
  // requests. The buffer size can be increased if required. Space
  // is also required for an HTTP_REQUEST structure.
  //
  RequestBufferLength = sizeof(HTTP_REQUEST) + 2048;
  pRequestBuffer      = (PCHAR) ALLOC_MEM( RequestBufferLength );
  
  if (pRequestBuffer == NULL)
  {
      return ERROR_NOT_ENOUGH_MEMORY;
  }
  
  pRequest = (PHTTP_REQUEST)pRequestBuffer;
  
  //
  // Wait for a new request. This is indicated by a NULL 
  // request ID.
  //
  
  HTTP_SET_NULL_ID( &amp;requestId );
  
  for(;;)
  {
      RtlZeroMemory(pRequest, RequestBufferLength);
  
      result = HttpReceiveHttpRequest(
                  hReqQueue,          // Req Queue
                  requestId,          // Req ID
                  0,                  // Flags
                  pRequest,           // HTTP request buffer
                  RequestBufferLength,// req buffer length
                  &amp;bytesRead,         // bytes received
                  NULL                // LPOVERLAPPED
                  );
            if(NO_ERROR == result)
      {
  
          DWORD answer = 0;
          HTTP_SSL_CLIENT_CERT_INFO sslClientCertInfo;
          ULONG bytesReceived;
          answer = HttpReceiveClientCertificate(hReqQueue, pRequest-&gt;ConnectionId, 0,
                  &amp;sslClientCertInfo, sizeof( HTTP_SSL_CLIENT_CERT_INFO ), &amp;bytesReceived, NULL );
  
  
          if (answer != NO_ERROR)
          {
            result = SendHttpResponse(hReqQueue, pRequest, 401, "Unauthorized request", "Unauthorized request");
          }
          else
          {
            result = SendHttpResponse(hReqQueue, pRequest, 200, "OK", "OK");
          }
  
          if (result != NO_ERROR)
          {
            break; //if failed to send response, stop listening for further incoming requests
          }
          //
          // Reset the Request ID to handle the next request.
          //
          HTTP_SET_NULL_ID( &amp;requestId );
      }
      else
      {
          break;
      }
  
  }
  if(pRequestBuffer)
  {
      FREE_MEM( pRequestBuffer );
  }
  
  return result;
  }
  
  
  
  /*******************************************************************++
  
  Routine Description:
  The routine sends a HTTP response
  
  Arguments:
  hReqQueue     - Handle to the request queue
  pRequest      - The parsed HTTP request
  StatusCode    - Response Status Code
  pReason       - Response reason phrase
  pEntityString - Response entity body
  
  Return Value:
  Success/Failure.
  --*******************************************************************/
  
  DWORD SendHttpResponse(
  IN HANDLE        hReqQueue,
  IN PHTTP_REQUEST pRequest,
  IN USHORT        StatusCode,
  IN PSTR          pReason,
  IN PSTR          pEntityString
  )
  {
  HTTP_RESPONSE   response;
  HTTP_DATA_CHUNK dataChunk;
  DWORD           result;
  DWORD           bytesSent;
  
  
  INITIALIZE_HTTP_RESPONSE(&amp;response, StatusCode, pReason);
  ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/html");
  
  
  if(pEntityString)
  {
      // 
      // Add an entity chunk.
      //
      dataChunk.DataChunkType           = HttpDataChunkFromMemory;
      dataChunk.FromMemory.pBuffer      = pEntityString;
      dataChunk.FromMemory.BufferLength = 
                                     (ULONG) strlen(pEntityString);
  
      response.EntityChunkCount         = 1;
      response.pEntityChunks            = &amp;dataChunk;
  }
  
  result = HttpSendHttpResponse(
                  hReqQueue,           // ReqQueueHandle
                  pRequest-&gt;RequestId, // Request ID
                  0,                   // Flags
                  &amp;response,           // HTTP response
                  NULL,                // pReserved1
                  &amp;bytesSent,          // bytes sent  (OPTIONAL)
                  NULL,                // pReserved2  (must be NULL)
                  0,                   // Reserved3   (must be 0)
                  NULL,                // LPOVERLAPPED(OPTIONAL)
                  NULL                 // pReserved4  (must be NULL)
                  ); 
  
  if(result != NO_ERROR)
  {
      wprintf(L"HttpSendHttpResponse failed with %lu \n", result);
  }
  
  return result;
  }
  </code></pre>
  
  <p>My problem is
  HttpReceiveClientCertificate
  Return 
  1168 
  ERROR_NOT_FOUND</p>
  
  <p>The function cannot find the client certificate. There is no guarantee that the client certificate will be available even if HTTPCFG is configured with /f 2 [Negotiate Client Cert].</p>
  
  <p><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa364494(v=vs.85).aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/windows/desktop/aa364494(v=vs.85).aspx</a></p>
  
  <p>thanks</p>