On Windows, 64-bit processes cannot load 32-bit DLLs, and 32-bit processes cannot load 64-bit DLLs. How does REGSVR32.EXE manage to successfully register both 32-bit and 64-bit COM DLLs?
SetWaitableTimer doesn't accept NULL for the pDueTime parameter. It returns FALSE; GetLastError() returns ERROR_NOACCESS (998). If you specify zero (i.e. a LARGE_INTEGER containing zero) for pDueTime, the timer is signalled immediately.
There are 10,000,000 FILETIME units (100ns) in a second. There are 10,000 FILETIME units (100ns) in a millisecond. Something like this might come in useful:
RegQueryValueEx, when passed lpData = NULL, will set *lpcbData to the length required in bytes, even if it's already set to something. If lpData != NULL, and *lpcbData is too short, RegQueryValueEx will return ERROR_MORE_DATA.
This means that you probably ought to call it in a loop, like this:
RegSetValueEx, when passed REG_SZ, needs the length to be in bytes, so don't just use _tcslen like this:
TCHAR sz[] = _T("Hello World");
RegSetValueEx(hKey, bstrValueName, 0, REG_SZ, (const BYTE *)sz, _tcslen(sz));
That truncates the value placed in the registry (11 bytes where it actually needed 24, including the null terminator).
RegSetValueEx, when passed REG_SZ, is documented as needing the length to include the NULL terminator.
You should hide your notification icon unless you've got something important to tell the user. More and more applications insist on putting mysterious icons in the notification area, and most users have no idea what they're for.
Like it says: NIM_SETVERSION always returns FALSE unless you've used NIM_ADD. So send NIM_ADD first.