Friday, July 10, 2009

Removing ATL from Your Code

Removing ATL from Your Code
COM is all over the place if you are doing win32 programming especially in higher level components like the shell. Should we be using COM as a Windows extension model in general is debatable, but we can leave that discussion for a later time. We want to talk about ATL.

The point of ATL is that it is supposed to help you write COM code more quickly by taking care of the tedious parts of COM programming like implementing IUnknown, managing ref counts, and freeing up memory; however, without going into too much gory detail, using ATL adds many high level dependencies not introduced by simple COM programming. If you are writing a higher level COM object that is already depending on things that use ATL or other high level dependencies, then maybe it doesn’t really matter if you are using ATL. Then it is really just a matter of preference. If you want to limit your high level dependencies and lower the level of you COM object, then you should avoid taking a dependency on ATL. Generally this is what you want to do if you want to write a low level system component that others will depend on and write extensions. I fall into this latter category for a component I want to clean up.

Unfortunately you may have some legacy COM code that took a dependency on ATL. If someone wanted depend on your component for use for something low level, then ATL could be a deal breaker. That is if COM already isn’t, but there are ways to make COM lean and mean without even using OLE. Take UMDF for example. This scenario is precisely the situation I am in. After coming back from vacation, I will be spending the next while removing ATL from some COM components. I will write on the things you need to do as I go through and figure out the processes.

Thursday, July 9, 2009

Supressing PreFAST Warnings

PreFAST is a great static analysis tool that can find lots of bugs for you; however, sometimes it can act like an over protective mother. In my last posts I NULL terminated the strings just to make PreFAST happy, but it felt more like a hack. I don't like leaving hacks in my real code. If there is a PreFAST warning that you feel like is unjustified and you would like you code to PreFAST warning free, you can use a handy #pragma trick to tell PreFAST that you know what you are doing and its okay. Keep in mind you don't want to do this very often, because generally PreFAST warnings should be fixed.

In my case, I was mallocing a buffer for a string that was to be read from the registry. PreFAST was warning me that I should NULL terminate the string. In this case RegEnumValue should do that correctly or give me an error. Since this warning is safe to ignore and I don't want to put in a hack just to get rid of the warning I added this #pragma at the line where the warning was:

#pragma prefast(suppress: 26036, "We expect that RegEnumValue will properly NULL terminate ppszKeyValue.")

Wednesday, July 8, 2009

Reading Registry Values Using RegEnumValue

This time I am pretending that I don’t know or care what the name of the value is. You can do that by using RegEnumValue. I wrote a function with this prototype:


__checkReturn HRESULT ReadKeyValue(
__in LPCWSTR pszSubKey,
__in DWORD dwIndex,
__deref_out LPWSTR *ppszKeyValue);

Basically you can read regkey values by its index. If you wanted to print out all of the values you could do it like this:

DWORD keyIndex = 0;

do
{
hr = HRESULT_FROM_WIN32(ReadKeyValue(psCategory, psSubcategory, keyIndex++, &psKeyValue));
wprintf(L"%s 0x%x\n", psKeyValue, hr);
if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) wprintf(L"this means there are no more key values\n");
} while (S_OK == hr);

So here is the complete function. If you knew that you were going to read a lot of values, you might want to open the regkey handle beforehand, do all of your reads, and close it when you are done. Other than that this code should look similar to the previous posting.

__checkReturn HRESULT ReadKeyValue(
__in LPCWSTR pszSubKey,
__in DWORD dwIndex,
__deref_out LPWSTR *ppszKeyValue)
{
HRESULT hr = S_OK;
LPWSTR pszSubKey = NULL;
HKEY hKey = NULL;
LPWSTR pszValueName = NULL;
DWORD lpcchValueName = 2048; // a reasonable initial buffer size
DWORD cbDataSize = 4096;
DWORD type = 0;

hr = HRESULT_FROM_WIN32(
RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
pszSubKey,
0,
KEY_QUERY_VALUE,
&hKey));

if (S_OK == hr)
{
*ppszKeyValue = (LPWSTR)malloc(cbDataSize);
pszValueName = (LPWSTR)malloc(lpcchValueName * sizeof(wchar_t));

if (!*ppszKeyValue || !pszValueName)
{
hr = E_OUTOFMEMORY;
}
else
{
**ppszKeyValue = L'\0';
*pszValueName = L'\0';
}
}

while (S_OK == hr && S_OK != (hr = HRESULT_FROM_WIN32(
RegEnumValue(
hKey,
dwIndex,
pszValueName,
&lpcchValueName ,
NULL,
&type,
(LPBYTE)*ppszKeyValue,
&cbDataSize))))
{
if (*ppszKeyValue)
{
free(*ppszKeyValue);
*ppszKeyValue = NULL;
}

if (pszValueName)
{
free(pszValueName);
pszValueName = NULL;
}

if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) == hr)
{
hr = S_OK;

*ppszKeyValue = (LPWSTR)malloc(cbDataSize);
pszValueName = (LPWSTR)malloc(lpcchValueName * sizeof(wchar_t));

if (!*ppszKeyValue || !pszValueName)
{
hr = E_OUTOFMEMORY;
}
else
{
**ppszKeyValue = L'\0'; // PreFAST is still whining about this
*pszValueName = L'\0';
}
}
else
{
break;
}
}

// cleanup
(void)RegCloseKey(hKey);

if (pszValueName)
{
free(pszValueName);
}

if (S_OK != hr && *ppszKeyValue)
{
free(*ppszKeyValue);
*ppszKeyValue = NULL;
}

return hr;
}

Posting Source Code in Blogger

It looks like blogger does not have a good built-in way to post code which is lame since this blog is supposed to be about code. For my last post I used a <pre> tag so the code didn't get foobared. The <pre> tag tells your browser to use a fixed width font and preserve the spacing. I supposed that is the easiest fix, and I will go with it for now.

Googling I found this (santaxhighlighter) other solution that looks more robust. I will do all of the santax highlighting and what not. It looks like it could be nice, but more overhead and annoyance.

I guess I could also use something like Word 2007 to publish to Blogger along with all of its bloated html.

It would be great if Blogger just provided a code mode.

Reading Values From the Registry Using RegGetValue

I am working on rewriting this section of code that needs to read key values from the registry.

First of all, if you already know what the key value is, you can get directly with RegGetValue.
// you should always use SAL annotations and the free static analysis tool PreFAST
__checkReturn HRESULT ReadKeyValue(
__in LPCWSTR pszSubKey,
__deref_out LPWSTR *ppszKeyValue)
{
HRESULT hr = S_OK;
DWORD cbDataSize = 4096;

*ppszKeyValue = NULL;

// This preallocates a reasonable size buffer for the value I want to read
// so that 99% of the time we only have to do one trip to the registry
if (!(*ppszKeyValue = (LPWSTR)malloc(cbDataSize)))
{
hr = E_OUTOFMEMORY;
}
else
{
**ppszKeyValue = L'\0'; // this makes PreFAST happy
}

while (S_OK == hr && S_OK != (hr = HRESULT_FROM_WIN32(
RegGetValue(
HKEY_LOCAL_MACHINE,
pszSubKey,
szRegValue,
RRF_RT_REG_SZ,
NULL,
*ppszKeyValue,
&cbDataSize))))
{
// if our preallocated buffer is not big enough, we will make it the
// exact size here and try the registry again
if (*ppszKeyValue)
{
free(*ppszKeyValue);
*ppszKeyValue = NULL;
}

if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) == hr)
{
hr = S_OK;

if(!(*ppszKeyValue = (LPWSTR)malloc(cbDataSize)))
{
hr = E_OUTOFMEMORY;
}
}
else
{
// this means we hit an unexpected failure
break;
}
}

// you should always clean up you memory on error states so you don't leak
if (S_OK != hr && *ppszKeyValue)
{
free(*ppszKeyValue);
*ppszKeyValue = NULL;
}

return hr;
}

Welcome to Sam's Code

I am starting this blog to journal my day to day coding. As I find out how to do new things, I will post them here. I have been doing a lot of device related systems programming on Windows. I will probably post those kind of things first. I also have tons of old stuff for low-level Linux/Unix and GPU programming that may or may not make it on here.