// SIM_ext.cpp : Implementation of CSIM_ext #include extern CComModule _Module; #include #include "Simext.h" #include "SIM_ext.h" #include static bool (*ProcessStr)(BSTR in_str, BSTR *out_str) = NULL; static string getToken(string &from, char c) { string res; unsigned i; for (i = 0; i < from.length(); i++){ if (from[i] == c) break; if (from[i] == '\\'){ i++; if (i >= from.length()) break; res += from[i]; continue; } res += from[i]; } if (i < from.length()){ from = from.substr(i + 1); }else{ from = ""; } return res; } HINSTANCE CSIM_ext::hInstance; ///////////////////////////////////////////////////////////////////////////// // CSIM_ext CSIM_ext::CSIM_ext() { lpData = NULL; if (ProcessStr == NULL){ char name[512]; GetModuleFileName(hInstance, name, sizeof(name)); char *r = strrchr(name, '\\'); if (r){ r++; }else{ r = name; } strcpy(r, "simremote.dll"); HINSTANCE hLib = LoadLibrary(name); (DWORD&)ProcessStr = (DWORD)GetProcAddress(hLib, "ProcessStr"); } } CSIM_ext::~CSIM_ext() { for (ICON_MAP::iterator it = m_icons.begin(); it != m_icons.end(); ++it) DestroyIcon((*it).second); if (lpData) lpData->Release(); } HRESULT CSIM_ext::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { if ((lpData == NULL) || (uFlags & CMF_DEFAULTONLY)) return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); CmdBase = idCmdFirst; if (((uFlags & 0x0000000F) == CMF_NORMAL) || (uFlags & CMF_EXPLORE)){ STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; FORMATETC formatetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; HRESULT hr = lpData->GetData(&formatetc, &stgmedium); if (!SUCCEEDED(hr)) return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); char *drop_files = (char*)GlobalLock(stgmedium.hGlobal); DROPFILES *files = (DROPFILES*)drop_files; GlobalUnlock(stgmedium.hGlobal); CComBSTR in("CONTACTS 3"); CComBSTR out; unsigned cmd_id = idCmdFirst; if (ProcessStr && ProcessStr(in, &out)){ HMENU hMain = NULL; HMENU hSub = NULL; size_t size = WideCharToMultiByte(CP_ACP, 0, out, wcslen(out), 0, 0, NULL, NULL); char *res = new char[size + 1]; size = WideCharToMultiByte(CP_ACP, 0, out, wcslen(out), res, size, NULL, NULL); res[size] = 0; if (res[0] == '>'){ string r = res + 1; string line = getToken(r, '\n'); unsigned nContacts = atol(getToken(line, ' ').c_str()); unsigned nGroups = atol(line.c_str()); bool bSubMenu = false; if ((nContacts > 20) && (nGroups > 1)){ hMain = CreatePopupMenu(); bSubMenu = true; } unsigned old_grp = (unsigned)(-1); while (!r.empty()){ line = getToken(r, '\n'); if (line.empty()) continue; unsigned id = atol(getToken(line, ' ').c_str()); unsigned grp = atol(getToken(line, ' ').c_str()); string icon = getToken(line, ' '); if (!line.empty()){ if (hMain){ if (grp != old_grp){ old_grp = grp; if (bSubMenu){ char *res = NULL; hSub = CreatePopupMenu(); char *grp = "Group"; char cmd[64]; sprintf(cmd, "GROUP %u", old_grp); CComBSTR in(cmd); CComBSTR out; if (ProcessStr && ProcessStr(in, &out)){ size_t size = WideCharToMultiByte(CP_ACP, 0, out, wcslen(out), 0, 0, NULL, NULL); char *res = new char[size + 1]; size = WideCharToMultiByte(CP_ACP, 0, out, wcslen(out), res, size, NULL, NULL); res[size] = 0; if (res[0] == '>') grp = res + 1; } AppendMenu(hMain, MF_POPUP | MF_STRING, (unsigned)hSub, grp); if (res) delete[] res; }else{ AppendMenu(hSub, MF_SEPARATOR, 0, NULL); } } }else{ hMain = CreatePopupMenu(); hSub = hMain; } ItemInfo info; info.text = line.c_str(); info.icon = createIcon(icon.c_str()); info.id = id; m_items.insert(ITEM_MAP::value_type(cmd_id, info)); AppendMenu(hSub, MF_STRING | MF_OWNERDRAW, cmd_id, line.c_str()); cmd_id++; } } } delete[] res; if (hMain != NULL) InsertMenu(hmenu, indexMenu++, MF_POPUP|MF_BYPOSITION, (UINT)hMain, "Send to SIM contact"); } return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, cmd_id - idCmdFirst); } return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); } static char fromHex(char c) { if ((c >= '0') && (c <= '9')) return (char)(c - '0'); if ((c >= 'A') && (c <= 'F')) return (char)(c + 10 - 'A'); if ((c >= 'a') && (c <= 'f')) return (char)(c + 10 - 'a'); return (char)0; } static void *unpackData(const char *p) { char *res = (char*)malloc(strlen(p) / 2); char *t = res; for (; p[0] && p[1]; p += 2) *(t++) = (fromHex(p[0]) << 4) + fromHex(p[1]); return res; } HBITMAP CSIM_ext::createBitmap(string &info) { BITMAPINFO *bmp = (BITMAPINFO*)unpackData(getToken(info, '\n').c_str()); void *bits = unpackData(getToken(info, '\n').c_str()); HDC hDC = CreateCompatibleDC(NULL); HBITMAP hRes = CreateBitmap(bmp->bmiHeader.biWidth, bmp->bmiHeader.biHeight, bmp->bmiHeader.biPlanes, bmp->bmiHeader.biBitCount, NULL); SetDIBits(hDC, hRes, 0, bmp->bmiHeader.biHeight, bits, bmp, DIB_RGB_COLORS); DeleteDC(hDC); free(bmp); free(bits); return hRes; } HICON CSIM_ext::createIcon(const char *name) { ICON_MAP::iterator it = m_icons.find(name); if (it != m_icons.end()) return (*it).second; string cmd = "ICON "; cmd += name; CComBSTR in(cmd.c_str()); CComBSTR out; if (!ProcessStr || !ProcessStr(in, &out)) return NULL; size_t size = WideCharToMultiByte(CP_ACP, 0, out, wcslen(out), 0, 0, NULL, NULL); char *res = new char[size + 1]; size = WideCharToMultiByte(CP_ACP, 0, out, wcslen(out), res, size, NULL, NULL); res[size] = 0; if (res[0] != '>') return NULL; string r = res + 1; ICONINFO info; info.fIcon = TRUE; info.xHotspot = 8; info.yHotspot = 8; info.hbmMask = createBitmap(r); info.hbmColor = createBitmap(r); HICON hIcon = CreateIconIndirect(&info); m_icons.insert(ICON_MAP::value_type(name, hIcon)); DeleteObject(info.hbmMask); DeleteObject(info.hbmColor); return hIcon; } #ifndef CF_HDROP #define CF_HDROP 15 #endif HRESULT CSIM_ext::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) { if (lpData == NULL) return S_OK; STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; FORMATETC formatetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; HRESULT hr = lpData->GetData(&formatetc, &stgmedium); if (SUCCEEDED(hr)){ char *drop_files = (char*)GlobalLock(stgmedium.hGlobal); DROPFILES *files = (DROPFILES*)drop_files; drop_files += files->pFiles; CComBSTR in("SENDFILE \""); if (files->fWide){ in += (unsigned short*)drop_files; }else{ in += drop_files; } in += "\" "; ItemInfo info = getItemInfo(LOWORD(lpici->lpVerb) + CmdBase); char b[12]; sprintf(b, "%u", info.id); in += b; GlobalUnlock(stgmedium.hGlobal); CComBSTR out; if (ProcessStr) ProcessStr(in, &out); } GlobalFree(stgmedium.hGlobal); if (lpData){ lpData->Release(); lpData = NULL; } return S_OK; } HRESULT CSIM_ext::HandleMenuMsg(UINT uMsg,WPARAM wParam, LPARAM lParam) { return HandleMenuMsg2(uMsg, wParam, lParam, NULL); } HRESULT CSIM_ext::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult) { switch(uMsg) { case WM_DRAWITEM: DrawMenuItem((LPDRAWITEMSTRUCT) lParam); break; case WM_MEASUREITEM: MeasureItem((LPMEASUREITEMSTRUCT) lParam); break; } return S_OK; } HRESULT CSIM_ext::GetCommandString(UINT idCmd, UINT uType, UINT * pwReserved, LPSTR pszName, UINT cchMax) { return S_OK; } HRESULT CSIM_ext::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY hkeyProgID) { if (lpData) lpData->Release(); lpData = lpdobj; lpData->AddRef(); return S_OK; } ItemInfo CSIM_ext::getItemInfo(unsigned id) { ITEM_MAP::iterator it = m_items.find(id); if (it != m_items.end()) return (*it).second; ItemInfo info; info.icon = NULL; return info; } void CSIM_ext::MeasureItem(LPMEASUREITEMSTRUCT lpmis) { if (lpmis->CtlType != ODT_MENU) return; ItemInfo info = getItemInfo(lpmis->itemID); if (info.icon == NULL) return; HDC hDC = CreateCompatibleDC(NULL); SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT)); SIZE s; GetTextExtentPoint32(hDC, info.text.c_str(), info.text.length(), &s); lpmis->itemWidth = s.cx + GetSystemMetrics(SM_CXMENUCHECK) + GetSystemMetrics(SM_CXFRAME) * 2; lpmis->itemHeight = GetSystemMetrics(SM_CYMENU); DeleteDC(hDC); } void CSIM_ext::DrawMenuItem(LPDRAWITEMSTRUCT lpdis) { if (lpdis->CtlType != ODT_MENU) return; ItemInfo info = getItemInfo(lpdis->itemID); if (info.icon == NULL) return; if (lpdis->itemAction & (ODA_DRAWENTIRE|ODA_SELECT)){ COLORREF crText, crBack; int bgColor; if (lpdis->itemState & ODS_SELECTED) { bgColor = COLOR_HIGHLIGHT; crText = SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); crBack = SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); }else{ bgColor = COLOR_MENU; } FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(bgColor)); ICONINFO icon_info; GetIconInfo(info.icon, &icon_info); BITMAP bmp; GetObject(icon_info.hbmColor, sizeof(BITMAP), (LPSTR)&bmp); DrawIconEx(lpdis->hDC, lpdis->rcItem.left + (GetSystemMetrics(SM_CXMENUCHECK) - bmp.bmWidth) / 2, lpdis->rcItem.top + (lpdis->rcItem.bottom - lpdis->rcItem.top - bmp.bmHeight) / 2, info.icon, bmp.bmWidth, bmp.bmHeight, 0, 0, DI_NORMAL); RECT rt = lpdis->rcItem; rt.left += GetSystemMetrics(SM_CXMENUCHECK) + GetSystemMetrics(SM_CXFRAME); DrawText(lpdis->hDC, info.text.c_str(), info.text.length(), &rt, DT_LEFT | DT_EXPANDTABS | DT_VCENTER | DT_SINGLELINE); if (lpdis->itemState & ODS_SELECTED) { SetTextColor(lpdis->hDC, crText); SetBkColor(lpdis->hDC, crBack); } } }