How to shoot yourself in the foot with const (or the lack thereof)

It has long puzzled me why various Win32 functions take non-const string parameters, when clearly they have no business manipulating the string.  Take, for instance, GetNamedSecurityInfo:

DWORD GetNamedSecurityInfo(
LPTSTR pObjectName,
PSID* ppsidOwner
PSID* ppsidGroup
PACL* ppDacl
PACL* ppSacl
PSECURITY_DESCRIPTOR* ppSecurityDescriptor


I can’t imagine why this function should ever need to write to pObjectName.  In fact, the SDK documentation explicitly lists it as an [in] parameter.  Also note that pObjectName is an LPTSTR.  This is important to the shooting of the foot.

A tidy, const-aware developer might want to do something like this:

const LPWSTR SomeFile = L”\\somefile.txt”;


GetNamedSecurityInfo(Somefile, …)

Of course, this will fail to compile, because SomeFile is const.  But casting solves this problem, right? 

GetNamedSecurityInfo((LPTSTR)Somefile, …)

Yay, this compiles.  Why, it even appears to return the correct data.

Fast forward a year or two, when suddenly the code stops working on Vista.  What could be wrong?  Why, in the process of casting away const, we’ve also turned an LPWSTR into an LPTSTR.  In this case, TCHAR resolved to char, so the code above was actually returning a security descriptor for “\\”.  Well, that is until Vista came along.

So while I hang my head in shame for being lame enough to cast between incompatible types, I will also caution the rest of you to consider whether your string parameters really need to be non-const, and avoid making your clients play casting games to use your API.  And yes, using const_cast<> might have prevented this issue, but I didn’t know about it at the time.  You, having read this far, have no excuse.


Comments (2)

  1. Peter Ritchie says:

    That sounds more like "how to shoot yourself in the foot with casting", it just happens the example uses const.