title: Clarify usage of WINHTTP_STATUS_CALLBACK function, for SSL status codes
body: <p><br>
  I'm writing some WinHttp code in C. I'm sending requests over SSL, and in order to handle SSL errors, I'm registering a <a href="http://msdn.microsoft.com/en-us/library/aa383917%28v=VS.85%29.aspx" rel="nofollow">WINHTTP_STATUS_CALLBACK function</a>, via a call to <a href="http://msdn.microsoft.com/en-us/library/aa384115%28VS.85%29.aspx" rel="nofollow">WinHttpSetStatusCallback</a> with dwNotificationFlags set to WINHTTP_CALLBACK_STATUS_SECURE_FAILURE. </p>
  
  <p>The documentation for WINHTTP_STATUS_CALLBACK says, that when the callback is invoked with <code>dwInternetStatus</code> = WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, it indicates that </p>
  
  <blockquote>
    <p>One or more errors were encountered while retrieving a Secure Sockets Layer (SSL) certificate from the server. The lpvStatusInformation parameter contains a flag. For more information, see the description for lpvStatusInformation.</p>
  </blockquote>
  
  <p>Now, the <code>lpvStatusInformation</code> parameter is typed as a LPVOID. But I take it from that statement in the documentation that it isn't treated as a pointer in the case of WINHTTP_CALLBACK_STATUS_SECURE_FAILURE. </p>
  
  <p>The doc for <code>lpvStatusInformation</code> says:</p>
  
  <blockquote>
    <p>If the dwInternetStatus parameter is WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, this parameter can be one of the following values.</p>
  </blockquote>
  
  <p>...And those values are one of these hex values: 1,2,4,8,10,20,40.  (See WinHttp.h)</p>
  
  <p>This seems pretty clear to me.  I shouldn't de-reference the pointer to get the value. the  <code>lpvStatusInformation</code> holds the hex value, not a pointer.</p>
  
  <p>Am I interpreting this correctly? </p>
  
  <hr>
  
  <p>I've written my code that way, and it has worked in the past.  I think!  However now I am getting a <code>lpvStatusInformation</code> of 0x0104f288.  That is nothing like any of those hex values. It's also not possible to create that value through OR'ing the possible values (though the doc says nothing about multiple status items in the same DWORD). It sure looks like a pointer to me.  And when I de-ref the pointer, I get 0x8, which corresponds to <code>WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA</code> , which at least makes sense. </p>
  
  <hr>
  
  <p>The question is, Should I de-reference that pointer, or not? </p>
  
  <p>Here's the callback code:</p>
  
  <pre><code>void CALLBACK Iirf_WinHttpSslStatusCallback( HINTERNET hInternet,
                                               DWORD_PTR context,
                                               DWORD code,
                                               void * pInfo,
                                               DWORD infoLength)
  {
      if (code == WINHTTP_CALLBACK_STATUS_SECURE_FAILURE) {
          ConfigInfo * cfg = (ConfigInfo *) context; // app-specific structure
          DWORD details = (DWORD) pInfo; // do not de-reference??
          CHAR buffer[32];
          CHAR * statusDescription = NULL;
  
          switch (details) {
              case WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED:
                  statusDescription = "CERT_REV_FAILED";
                  break;
  
              case WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT:
                  statusDescription = "INVALID_CERT";
                  break;
  
              case WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED:
                  statusDescription = "CERT_REVOKED";
                  break;
  
              case WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA:
                  statusDescription = "INVALID_CA";
                  break;
  
              case WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID:
                  statusDescription = "CERT_CN_INVALID";
                  break;
  
              case WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID:
                  statusDescription = "CERT_DATE_INVALID";
                  break;
  
              case WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR:
                  statusDescription = "SECURITY_CHANNEL_ERROR";
                  break;
  
              default:
                  statusDescription = buffer;
                  sprintf_s(buffer, 32, "stat(0x%08X) len(%d)",
                            details, infoLength);
                  break;
          }
  
          LogMessage(cfg, 1, "SslStatusCallback: %s", statusDescription);
      }
  }
  </code></pre>