#include #include #include #include "stringutils.h" #include "debug.h" #include "args.h" // see c:/Program Files/Windows Mobile 6 SDK/Smartphone/Include/Armv4i/aygshell.h // z:/sources/wm500aku/PUBLIC/SHELLW/SDK/INC/aygshell.h // // notification update mask // #define SHNUM_PRIORITY 0x0001 // #define SHNUM_DURATION 0x0002 // #define SHNUM_ICON 0x0004 // #define SHNUM_HTML 0x0008 // #define SHNUM_TITLE 0x0010 // #define SHNUM_SOFTKEYS 0x0020 // #define SHNUM_TODAYKEY 0x0040 // #define SHNUM_TODAYEXEC 0x0080 // #define SHNUM_SOFTKEYCMDS 0x0100 // #define SHNUM_FLAGS 0x0200 // // // // bool parseguid(CLSID& clsid, const std::string & str) { const std::string hexchars= "0123456789abcdefABCDEF"; int n= sscanf(str.c_str(), "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", &clsid.Data1, &clsid.Data2, &clsid.Data3, clsid.Data4+0, clsid.Data4+1, clsid.Data4+2, clsid.Data4+3, clsid.Data4+4, clsid.Data4+5, clsid.Data4+6, clsid.Data4+7); return n==11; } void init_shn(SHNOTIFICATIONDATA*shn) { memset(shn, 0, sizeof(*shn)); shn->cbStruct= sizeof(*shn); } std::string ShnFlagsString(DWORD f) { StringList l; if (f&SHNF_STRAIGHTTOTRAY) l.push_back("STRAIGHTTOTRAY"); if (f&SHNF_CRITICAL ) l.push_back("CRITICAL"); if (f&SHNF_FORCEMESSAGE ) l.push_back("FORCEMESSAGE"); if (f&SHNF_DISPLAYON ) l.push_back("DISPLAYON"); if (f&SHNF_SILENT ) l.push_back("SILENT"); if (f&SHNF_HASMENU ) l.push_back("HASMENU"); if (f&SHNF_TITLETIME ) l.push_back("TITLETIME"); if (f&SHNF_SPINNERS ) l.push_back("SPINNERS"); if (f&SHNF_ALERTONUPDATE ) l.push_back("ALERTONUPDATE"); if (f&SHNF_WANTVKTTALK ) l.push_back("WANTVKTTALK"); DWORD all=SHNF_STRAIGHTTOTRAY|SHNF_CRITICAL|SHNF_FORCEMESSAGE|SHNF_DISPLAYON|SHNF_SILENT|SHNF_HASMENU|SHNF_TITLETIME|SHNF_SPINNERS|SHNF_ALERTONUPDATE|SHNF_WANTVKTTALK; if (f&~all) { l.push_back(stringformat("SHNFLAG_%08lx", f&~all)); } return JoinStringList(l, ","); } void dump_shn(SHNOTIFICATIONDATA* shn) { if (shn->cbStruct!=sizeof(*shn)) debug("NOTE: structsize = 0x%x ( expected 0x%x )\n", shn->cbStruct, sizeof(*shn)); debug("id : %08lx\n", shn->dwID); debug("npPriority: %s\n", shn->npPriority==SHNP_INFORM?"INFORM":shn->npPriority==SHNP_ICONIC?"ICONIC":stringformat("%08lx", shn->npPriority).c_str()); debug("csDuration: %08lx\n", shn->csDuration); debug("hicon : %08lx\n", shn->hicon); debug("grfFlags : %s\n", ShnFlagsString(shn->grfFlags).c_str()); debug("clsid : %08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", shn->clsid.Data1, shn->clsid.Data2, shn->clsid.Data3, shn->clsid.Data4[0], shn->clsid.Data4[1], shn->clsid.Data4[2], shn->clsid.Data4[3], shn->clsid.Data4[4], shn->clsid.Data4[5], shn->clsid.Data4[6], shn->clsid.Data4[7]); debug("hwndSink : %08lx\n", shn->hwndSink); debug("pszHTML : %ls\n", shn->pszHTML); debug("pszTitle : %ls\n", shn->pszTitle); debug("lParam : %08lx\n", shn->lParam); if (shn->grfFlags&SHNF_HASMENU) { debug("skm : \n"); debug(" hMenu : %08lx\n", shn->skm.hMenu); debug(" cskc : %08lx\n", shn->skm.cskc); for (DWORD i=0 ; iskm.cskc ; i++) debug(" prgskc[%2d] : %08lx %s\n", i, shn->skm.prgskc[i].wpCmd, ShnFlagsString(shn->skm.prgskc[i].grfFlags).c_str()); } else { for (int i=0 ; i<2 ; i++) { debug("rgskn%d : \n", i); debug(" pszTitle : %ls\n", shn->rgskn[i].pszTitle); debug(" wpCmd : %08lx\n", shn->rgskn[i].skc.wpCmd); debug(" grfFlags : %s\n", ShnFlagsString(shn->rgskn[i].skc.grfFlags).c_str()); } } debug("pszTodaySK: %ls\n", shn->pszTodaySK); debug("pszTodayExec: %ls\n", shn->pszTodayExec); } // value for flags: // SHNF_STRAIGHTTOTRAY 0x0001 // SHNF_CRITICAL 0x0002 // Critical information - highlights the border and title of the bubble. // SHNF_FORCEMESSAGE 0x0008 // Force the message (bubble) to display even if settings says not to. // SHNF_DISPLAYON 0x0010 // Force the display to turn on for notification. // SHNF_SILENT 0x0020 // Force the notification to be silent and not vibrate, regardless of Settings // SHNF_HASMENU 0x0040 // Softkey bar is created from an HMENU passed in skm structure // SHNF_TITLETIME 0x0080 // Draw the current time with the title // SHNF_SPINNERS 0x0100 // A notification with "stack" support // SHNF_ALERTONUPDATE 0x0200 // RE-play physical alerts on an update // SHNF_WANTVKTTALK 0x0400 //Capture the VK_TTALK button and forward it to the notification's sink window void usage() { debug("options:\n"); debug(" -a add\n"); debug(" -r remove\n"); debug(" -g get info\n"); debug(" -u MASK update\n"); debug(" -c GUID specify clsid to use\n"); debug(" -f FLAGS specify flags\n"); debug(" -i ID specify id\n"); debug(" -t 'title'\n"); debug(" -h 'html'\n"); debug(" -d TIME specify duration\n"); debug(" -l PARAM specify lparam\n"); debug(" -p [1|2] specify priority\n"); debug(" -s todaysk\n"); debug(" -x tdexec\n"); debug(" -n dll:rsid specify icon\n"); debug(" -w HWND specify hwnd sink\n"); } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { DebugSetLogfile("tstnot.log"); debug("\n"); StringList args; if (!SplitString(ToString(lpCmdLine), args, false)) { error("Error in commandline"); return false; } int action=0; #define ACT_ADD 1 #define ACT_UPD 2 #define ACT_REM 3 #define ACT_GET 4 DWORD updmask=0; SHNOTIFICATIONDATA shn; std::string title; std::string html; std::string todaysk; std::string todayexec; DWORD priority=0; init_shn(&shn); // examples: // tstnot -a -i 1234 -c 28C86349-5F9E-4c21-A4BB-C18B4251D3BB // tstnot -g -c 28C86349-5F9E-4c21-A4BB-C18B4251D3BB for (StringList::iterator i= args.begin() ; i!=args.end() ; ++i) { std::string& arg= *i; if (arg[0]=='-') switch(arg[1]) { case 'a': action= ACT_ADD; break; case 'r': action= ACT_REM; break; case 'g': action= ACT_GET; break; case 'u': HANDLESTLULOPTION(updmask, DWORD); action= ACT_UPD; break; case 'c': parseguid(shn.clsid, arg[2] ? arg.substr(2) : i+1!=args.end() ? *(++i) : ""); break; case 'f': HANDLESTLULOPTION(shn.grfFlags, DWORD); break; case 'i': HANDLESTLULOPTION(shn.dwID, DWORD); break; case 't': HANDLESTLSTRCOMBIOPTION(title); shn.pszTitle= _tcsdup(ToWString(title).c_str()); break; case 'h': HANDLESTLSTRCOMBIOPTION(html); shn.pszHTML= _tcsdup(ToWString(html).c_str()); break; case 'd': HANDLESTLULOPTION(shn.csDuration, DWORD); break; case 'l': HANDLESTLULOPTION(shn.lParam, DWORD); break; case 'p': HANDLESTLULOPTION(priority, DWORD); break; case 's': HANDLESTLSTRCOMBIOPTION(todaysk); shn.pszTodaySK= _tcsdup(ToWString(todaysk).c_str()); break; case 'x': HANDLESTLSTRCOMBIOPTION(todayexec); shn.pszTodayExec= _tcsdup(ToWString(todayexec).c_str()); break; case 'w': HANDLESTLULOPTION(shn.hwndSink, HWND); break; case 'n': // todo: get icon handle default: usage(); } } if (priority==1) shn.npPriority= SHNP_INFORM; else if (priority==2) shn.npPriority= SHNP_ICONIC; else debug("unsupported priority: %d\n", priority); LRESULT lr; switch(action) { case ACT_ADD: debug("adding notification\n"); lr= SHNotificationAdd(&shn); if (lr) { debug("ERROR SHNotificationAdd: %08lx\n", lr); } break; case ACT_UPD: debug("updating notification\n"); lr= SHNotificationUpdate(updmask, &shn); if (lr) { debug("ERROR SHNotificationUpdate: %08lx\n", lr); } break; case ACT_REM: debug("removing notification\n"); lr= SHNotificationRemove(&shn.clsid, shn.dwID); if (lr) { debug("ERROR SHNotificationRemove: %08lx\n", lr); } break; case ACT_GET: debug("getting notification info\n"); lr= SHNotificationGetData(&shn.clsid, shn.dwID, &shn); if (lr) { debug("ERROR SHNotificationGetData: %08lx\n", lr); } dump_shn(&shn); break; default: debug("unknown action: %d\n", action); } return 0; }