tags:

views:

66

answers:

4

In WinCrypt.h I see:

#define CERT_CHAIN_POLICY_SSL   ((LPCSTR) 4)

WINCRYPT32API BOOL WINAPI CertVerifyCertificateChainPolicy(
    IN LPCSTR pszPolicyOID,
    IN PCCERT_CHAIN_CONTEXT pChainContext,
    IN PCERT_CHAIN_POLICY_PARA pPolicyPara,
    IN OUT PCERT_CHAIN_POLICY_STATUS pPolicyStatus
    );

The first argument takes CERT_CHAIN_POLICY_SSL. This appears to be a pointer to a C string, yet it is an integer!?

The pointer is obviously a 32bit integer, but what is it pointing at? If the number is < 255 it will take up a single byte, so is the C string in fact a single byte "string" (ie a byte)?

When conveting to another language that does support BYTE variables, I can just create a bVar (a BYTE variable) and assign it 4. Then I can pass a pointer to that BYTE variable?

+1  A: 

The pointer isn't pointing at anything. On a 32-bit system, it will be a (almost certainly invalid) pointer with value 0x00000004.

As for other languages, in C# for example it is likely to be marshalled as a System.IntPtr.

You could think of this nasty casting as a lazy way of doing

union StringOrInteger
{
  const char* str;
  int n;
};
James Hopkin
A: 

No, you can't pass a pointer to a BYTE holding the value. That would lead to the C API "seeing" a pointer value that is a true address (the address of that BYTE), not the small integer passed as a pointer that it expects.

There's no string, it's just using the pointer value by itself. That it happens to be declared as a pointer to a string doesn't matter, it could just as well be a pointer to a float, or (better) void*.

unwind
+1  A: 

You have to understand that some APIs are designed to be as short and compact as possible, even if it means potentially confusing users. For example the CreateDialog function allows you to specify a string resource identifier. But you can also specify integer identifiers. So Microsoft decided that you could pass an integer ID in the same argument (a pointer!). It may be the same thing here - this function may be allowing you to specify a string policy ID or an integer one. For compactness, both forms are passed in the same argument.

wj32
Just curious, how would you point to a string policy when the pointer IS the value required?
Mike Trader
You pass the string pointer. There would be some limit to the range of possible integer indentifiers - for example, values below 0x1000 could be reserved for them, since those pages are actually unusable and cannot possibly contain strings.
wj32
+1  A: 

Sometimes an API will take a parameter that can be a 'cookie' or ID for a well-known object or a pointer to a name (for example),which is what appears to be the case here. 4 is a cookie/handle/ID for the well-known CERT_CHAIN_POLICY_SSL policy. Some users of the API might specify a policy that's not known to the library ahead of time, but is specified by a name that the it can look up somewhere (or like the registry, config file or something).

In a somewhat similar vein, GetProcAddress() can take a pointer to the name of the function you want the address for (which is how it's used 99% of the time today), or the pointer-to-a-string parameter can be a number that specifies the ordinal of the function.

Overloading pointer parameters like this is an unfortunate techniques that's sometimes used to make an API more flexible. Fortunately it's not particularly common.

Anyway, if you want to call this API from another language and specify the CERT_CHAIN_POLICY_SSL policy, you need to pass a 4 for the pointer's value (not a pointer pointing to the value 4).

Michael Burr
Great work, now my answer won't get voted up because yours is longer! :)
wj32