Fun with MSN Messenger's "Now Playing" function
Since version 7, MSN Messenger has the ability to show what music you're listening to in your screenname. The function was made to be used in conjuction with Windows Media Player, but it's also supported by iTunes and, via plugins, by Winamp and Foobar.
How it works
The Now Playing information is sent to MSN by storing it in a string which is put in a COPYDATASTRUCT and sent via a WM_COPYDATA window message. After some experimentation it seems the Now Playing info can be updated about once every six seconds, not faster. The string put into the COPYDATASTRUCT has the following layout:
\\0\\Music\\0[on/off]\\0[format]\\0[title]\\0[artist]\\0[album]\\0\\0
| Music | The type of Now Playing information. "Office" and "Games" are also valid. The rest of the string stays the same, these only determine which icon is shown in MSN. |
| [on/off] | 1 to activate Now Playing, 0 to disable it and clear the user's name |
| [format] | Formatting string. {0} {1} and {2} are title, artist and album (see examples) |
| [title] | Song title |
| [artist] | Song artist |
| [album] | Song album |
For example, to turn Now Playing off the string would be:
\\0\\Music\\00\\0\\0
And to set it to "My Sanctuary by Pig from Praise the Lard":
\\0Music\\01\\0{0} by {1} from {2}\\0My Sanctuary\\0PIG\\0Praise the Lard\\0\\0
Sample code
The following C code snippet includes a function to set and clear the Now Playing info, and sets it using above example: nowplaying.c. Make sure to compile it with Unicode support!
As a bonus example, you can use the following main() code to show what program you're currently using in your MSN name (needs psapi.h and psapi.lib, which are part of the normal Windows SDK). You can download the compiled version of it here.
while(1)
{
HANDLE currProcH;
wchar_t currExePath[MAX_PATH+1];
wchar_t* currExe;
HWND currWindow;
DWORD currProcID;
currWindow = GetForegroundWindow(); //Get HWND of focused Window
GetWindowThreadProcessId(currWindow,&currProcID); //Get matching process
currProcH = OpenProcess(PROCESS_QUERY_INFORMATION,0,currProcID); //Open handle to process
GetProcessImageFileName(currProcH,currExePath,MAX_PATH); //Get .exe path for process
CloseHandle(currProcH); //Close process
//Get the .exe name from the path
currExe = wcsrchr(currExePath,'\\')+1;
if(!currExe) //If there wasn't a directory before the exe name, use the path as-is
currExe=currExePath;
_putws(currExe);
setNowPlaying(L"{0}",currExe,L"John Doe",L""); //Set Now Playing info
Sleep(6000);
}