Programming magic, glory, and juices.

A SET without a GET?!!

June 9th, 2008


How is it possible that Microsoft didn’t introduce PBM_GETBKCOLOR/PBM_GETBARCOLOR until Windows Vista? I mean, I can’t imagine it! The progress bar messages PBM_SETBKCOLOR and PBM_SETBARCOLOR are supported in Windows 95+, but it took them until Vista to develop PBM_GETBKCOLOR and PBM_GETBARCOLOR??!! How do failures like that go overlooked for such a long period of time?

ResHacker bug

April 8th, 2008


Was working on my utility today that injects an icon into an executable and found out that ResHacker does not support icons that are 256×256 pixels. It is actually a bug, because in the ICONDIRENTRY structure, which defines an icon in an icon group, the Width and Height properties are defined as BYTE’s. Well a BYTE cannot hold the value 256. So, instead the common practice has been to use 0 to indicate the value of 256. When ResHacker sees the value of Width and Height as 0 it thinks it has run out of memory and so throws a “Out of system resources” error message.

I wrote the author of the program, but the website says ResHacker it is no longer under development and that I should use XN Resource Editor. Too bad it doesn’t support drag and drop thou.

Wikipedia Icon File Format

Supporting Unicode

January 6th, 2008


Windows’ Unicode Support
All internal functions in Windows use the Unicode format UTF16 natively. The book Windows Internals mentions that when a developer calls an the ANSI version of a function that Windows converts all the function’s parameters that are ANSI strings to Unicode and calls the Unicode version of the function. Then when the Unicode function is finished, Windows will then convert the Unicode result strings back to ANSI and return. ReactOS which is modeled off Windows allocates a new string buffer for each conversion that needs to take place.

String Library
Such string conversion layers work well for a higher level API, but for core API or for a string library it would not do. It would be insane to have to do a ANSI to Unicode conversion for each string function needing to be called. You would have to allocate a new string buffer each time you wanted to call a string function.

When ends up happening with string libraries is that a lot of duplicate code ends up being created. For each string function multiple encoding format functions have to be written. And this is done so that 1). you don’t encur the overhead cost of conversion and 2). for side-by-side encoding support. Having side-by-side encoding support is important because you’ll find you end up needing to use encoding formats other than the default encoding format that you are building your project in.

Side-by-side support for ANSI/ASCII and Unicode/UTF16

#ifdef UNICODE
#define String_Copy   StringUtf16_Copy
#else
#define String_Copy   StringAscii_Copy
#endif

int32 StringUtf16_Copy(wchar *Target, wchar *Source);
int32 StringAscii_Copy(char *Target, char *Source);

In the code example above, you can call String_Copy to copy a string based on the build encoding for your project or if you need to explictly call the UTF16 or ASCII versions of String_Copy throughout your code you can do that as well.

Windows API macros are set up the exact same way, the only difference is that the ANSI functions call Unicode functions, something which is not reasonable to do with a string library due to the conversion overhead.

TCHAR
Most functions won’t need side-by-side support in that you’ll need both an ANSI version and a Unicode version. For these functions we can use TCHAR which is defined as the char type for the current project’s build encoding.

#ifdef UNICODE
#define tchar   wchar
#else
#define tchar   char
#endif

int32 File_Open(int32 FileHandle, tchar *Filename, int32 Flags);

Naming
Naming conventions are always important. The cleaner you name your functions and variables the better. Windows names the ANSI version of a function by appending an ‘A’ and a Unicode version of a function by appending a ‘W’ for wide char. For instance in Windows their is a LoadImageA and LoadImageW and the LoadImage macro selects which function to call based on the character encoding for your project. If I were to do the same thing I would have ended up with String_CopyA and String_CopyW. Or I could do it the exact opposite and name it how the C runtime library does and prepend a ‘w’ only on Unicode functions in which case I would end up with String_Copy and WString_Copy. Too me neither really look right. So because the character encoding type is not recongizable in the letters ‘A’ and ‘W’ I decided to use the name of the format appended to the end of the class name. What would I do if I had to add another character encoding to the string library? Add an ‘X’? Functions that use multiple character encodings will have variable names in the format Filename for ASCII, Filename8 for UTF8, and Filename16 for UTF16.

Happy Coding. The End.

Delete IE Cache the Right Way

November 3rd, 2006


There are some really awful examples out there on how to delete the cache in Internet Explorer using the Windows API. The method is simple, but the implementation is difficult.

To be able to delete all the cache entries you must first iterate through them. You can do this using FindFirstUrlCacheEntry and FindNextUrlCacheEntry. These two functions are possibly the worst iteration functions to come out of Microsoft.

Deleting each cache entry during each iterating can lead to problems, mainly the possibility that not all the cache entries will be deleted. I believe I read a newsgroup posting that said FindFirstUrlCacheEntry and FindNextUrlCacheEntry get confused when using DeleteUrlCacheEntry during each iteration. I’ve found that doing so will only remove about 10% of the total cache entries.

Let me explain FindFirstUrlCacheEntry and its brother function a moment. They both require a variable length buffer to be able to store information about the next cache entry during iteration. Furthermore you can get the length of the required buffer by either passing the function an allocation with not enough memory or by not passing the function anything. Each time you call either FindFirstUrlCacheEntry or FindNextUrlCacheEntry you must pass in a pointer to a integer that specifies the size of the buffer that you are also passing in. Failure to set this size parameter’s value before calling these functions will result in further problems.

So here is the plan. First iterate through each cache entry using FindFirstUrlCacheEntry and FindNextUrlCacheEntry. While iterating create a new memory buffer that houses that particular cache entry’s information. When we are done iterating through all cache entries we delete them one by one using DeleteUrlCacheEntry. After all cache entries have been deleted we free the remaining memory that stores each cache entries information.

Not all the required code is represented here.

uint32 Size = 0;
HANDLE Handle;
LPINTERNET_CACHE_ENTRY_INFO Info;

/* Get the size of the first cache entry */

FindFirstUrlCacheEntry(NULL, NULL, &Size);

// TODO: Allocate new buffer "Info" with the length of "Size"
// TODO: Add buffer "Info" to linked list for later deletion

Handle = FindFirstUrlCacheEntry(NULL, Info, &Size);

while ((Handle != NULL) && (GetLastError() != ERROR_NO_MORE_ITEMS))
    {
    /* Zero out "Size" so we can check for next entry's required buffer size */

    Size = 0;

    /* Get next entry's buffer size */

    FindNextUrlCacheEntry(Handle, NULL, &Size);

    if (Size == 0)
        break;

    // TODO: Create new buffer "Info" with length of Size
    // TODO: Add "Info" to linked list for later deletion

    if (FindNextUrlCacheEntry(Handle, Info, &Size) == FALSE)
        break;
    }

FindCloseUrlCache(Handle);

This is the best way to iterate through Internet Explorer’s cache. First get the buffer size required to house each entry’s data then retrieve it. That way you don’t have to check for ERROR_INSUFFICIENT_BUFFER because you know you’ll always have the right sized buffer. Trying to have a single memory buffer that you continuously resize by is too messy. Actually deleting each cache entry is simple, just iterate through each item in your linked list called call DeleteUrlCacheEntry with the cache data that you have stored. When everything has been deleted then free each item in your linked list. Didn’t I say it was easy as a piece of crumb cake?

Win32 Setting a Directory’s Date & Time

June 4th, 2006


Below is code that will allow you to set the date and time of a directory in windows using a dos datetime stamp.

int32 Directory_SetDosTime(char *Path, uint32 DosDateTime)
{
   FILETIME LocalTime, FileTime;
   HANDLE Handle;
   SYSTEMTIME SystemTime;

   Debug_AssertPointer(Path);

   DosDateTimeToFileTime((DosDateTime >> 16), DosDateTime, &LocalTime);
   LocalFileTimeToFileTime(&LocalTime, &FileTime);
   FileTimeToSystemTime(&FileTime, &SystemTime);

   Handle = CreateFile(Path, GENERIC_WRITE, FILE_SHARE_WRITE,
         NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);

   if (Handle == INVALID_HANDLE_VALUE)
      {
      Debug_Print("Unable to open directory [%s]\n”, Path);
      return FALSE;
      }

   if (SetFileTime(Handle, &FileTime, &FileTime, &FileTime) == 0)
      {
      Debug_Print(”Unable to set directory time\n”);
      CloseHandle(Handle);
      return FALSE;
      }

   CloseHandle(Handle);
   return TRUE;
}

Windows GUI Regions

May 8th, 2006


When you are done using a region in Windows GUI you should call

SelectClipRgn(hDC, NULL);

To select a deselect the most recently selected region so that your continued drawing efforts don’t go in vain.

Bad MSDN Example Code

May 4th, 2006


The following MSDN page entitled Custom Draw Overview gives sample source code using a constant called CDRF_NOTIFYSUBITEMREDRAW. Most likely it is a bad copy on CDRF_NOTIFYSUBITEMDRAW. There is no CDRF_NOTIFYSUBITEMREDRAW in commctrl.h and Visual Studio could not locate the definition for CDRF_NOTIFYSUBITEMREDRAW.