/* * YAMN plugin main file * Miranda homepage: http://miranda-icq.sourceforge.net/ * YAMN homepage: http://www.majvan.host.sk/Projekty/YAMN * * initializes all variables for further work * * (c) majvan 2002-2004 */ #include "yamn.h" //-------------------------------------------------------------------------------------------------- TCHAR ProfileName[MAX_PATH]; TCHAR UserDirectory[MAX_PATH]; TCHAR szMirandaDir[MAX_PATH]; TCHAR szProfileDir[MAX_PATH]; int YAMN_STATUS; BOOL UninstallPlugins; HANDLE hAccountFolder; HINSTANCE *hDllPlugins; static int iDllPlugins = 0; YAMN_VARIABLES YAMNVar; int hLangpack; PLUGININFOEX pluginInfo = { sizeof(PLUGININFOEX), __PLUGIN_NAME, PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), __DESCRIPTION, __AUTHOR, __AUTHOREMAIL, __COPYRIGHT, __AUTHORWEB, UNICODE_AWARE, // {B047A7E5-027A-4CFC-8B18-EDA8345D2790} {0xb047a7e5, 0x27a, 0x4cfc, {0x8b, 0x18, 0xed, 0xa8, 0x34, 0x5d, 0x27, 0x90}} }; HANDLE hNewMailHook; HANDLE NoWriterEV; HANDLE hTTButton; UINT SecTimer; HANDLE hMenuItemMain = 0; HANDLE hMenuItemCont = 0; HANDLE hMenuItemContApp = 0; HMODULE hUxTheme = 0; BOOL (WINAPI *MyEnableThemeDialogTexture)(HANDLE, DWORD) = 0; // function pointers, use typedefs for casting to shut up the compiler when using GetProcAddress() typedef BOOL (WINAPI *PITA)(); typedef HANDLE (WINAPI *POTD)(HWND, LPCWSTR); typedef UINT (WINAPI *PDTB)(HANDLE, HDC, int, int, RECT *, RECT *); typedef UINT (WINAPI *PCTD)(HANDLE); typedef UINT (WINAPI *PDTT)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, RECT *); PITA pfnIsThemeActive = 0; POTD pfnOpenThemeData = 0; PDTB pfnDrawThemeBackground = 0; PCTD pfnCloseThemeData = 0; PDTT pfnDrawThemeText = 0; #define FIXED_TAB_SIZE 100 // default value for fixed width tabs /* * visual styles support (XP+) * returns 0 on failure */ int InitVSApi() { if ((hUxTheme = LoadLibraryA("uxtheme.dll")) == 0) return 0; pfnIsThemeActive = (PITA)GetProcAddress(hUxTheme, "IsThemeActive"); pfnOpenThemeData = (POTD)GetProcAddress(hUxTheme, "OpenThemeData"); pfnDrawThemeBackground = (PDTB)GetProcAddress(hUxTheme, "DrawThemeBackground"); pfnCloseThemeData = (PCTD)GetProcAddress(hUxTheme, "CloseThemeData"); pfnDrawThemeText = (PDTT)GetProcAddress(hUxTheme, "DrawThemeText"); MyEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, "EnableThemeDialogTexture"); if (pfnIsThemeActive != 0 && pfnOpenThemeData != 0 && pfnDrawThemeBackground != 0 && pfnCloseThemeData != 0 && pfnDrawThemeText != 0) return 1; return 0; } /* * unload uxtheme.dll */ int FreeVSApi() { if (hUxTheme != 0) FreeLibrary(hUxTheme); return 0; } //-------------------------------------------------------------------------------------------------- static void GetProfileDirectory(TCHAR *szPath, int cbPath) //This is copied from Miranda's sources. In 0.2.1.0 it is needed, in newer vesions of Miranda use MS_DB_GETPROFILEPATH service { TCHAR tszOldPath[MAX_PATH]; CallService(MS_DB_GETPROFILEPATHT, SIZEOF(tszOldPath), (LPARAM)tszOldPath); _tcscat(tszOldPath, _T("\\*.book")); VARST ptszNewPath( _T("%miranda_userdata%")); SHFILEOPSTRUCT file_op = { NULL, FO_MOVE, tszOldPath, ptszNewPath, FOF_NOERRORUI | FOF_NOCONFIRMATION | FOF_SILENT, false, 0, _T("") }; SHFileOperation(&file_op); _tcsncpy(szPath, ptszNewPath, cbPath); } ///////////////////////////////////////////////////////////////////////////////////////// extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { YAMNVar.hInst = hinstDLL; return TRUE; } ///////////////////////////////////////////////////////////////////////////////////////// extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) { return &pluginInfo; } ///////////////////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG static TCHAR unknownCP[1500] = {0}; #endif // The callback function BOOL CALLBACK EnumSystemCodePagesProc(LPTSTR cpStr) { //Convert code page string to number UINT cp = _ttoi(cpStr); if (!IsValidCodePage(cp)) return TRUE; //Get Code Page name CPINFOEX info; if (GetCPInfoEx(cp, 0, &info)) { #ifdef _DEBUG BOOLEAN found = FALSE; #endif for (int i = 1;i= SIZEOF(iconList)) return NULL; return iconList[idx].hIcolib; } HICON WINAPI g_LoadIconEx( int idx, bool big ) { if ( idx >= SIZEOF(iconList)) return NULL; return Skin_GetIcon(iconList[idx].szName, big); } void WINAPI g_ReleaseIcon( HICON hIcon ) { if ( hIcon ) Skin_ReleaseIcon(hIcon); } static void LoadPlugins() { HANDLE hFind; WIN32_FIND_DATA fd; TCHAR szSearchPath[MAX_PATH]; TCHAR szPluginPath[MAX_PATH]; lstrcpy(szSearchPath, szMirandaDir); lstrcat(szSearchPath, _T("\\Plugins\\YAMN\\*.dll")); typedef INT_PTR (*LOADFILTERFCN)(MIRANDASERVICE GetYAMNFcn); hDllPlugins = NULL; if (INVALID_HANDLE_VALUE != (hFind = FindFirstFile(szSearchPath, &fd))) { do { //rewritten from Miranda sources... Needed because Win32 API has a bug in FindFirstFile, search is done for *.dlllllll... too TCHAR *dot = _tcsrchr(fd.cFileName, '.'); if (dot == NULL ) continue; // we have a dot int len = (int)lstrlen(fd.cFileName); // find the length of the string TCHAR* end = fd.cFileName+len; // get a pointer to the NULL int safe = (end-dot)-1; // figure out how many chars after the dot are "safe", not including NULL if ((safe != 3) || (lstrcmpi(dot+1, _T("dll")) != 0)) //not bound, however the "dll" string should mean only 3 chars are compared continue; HINSTANCE hDll; LOADFILTERFCN LoadFilter; lstrcpy(szPluginPath, szMirandaDir); lstrcat(szPluginPath, _T("\\Plugins\\YAMN\\")); lstrcat(szPluginPath, fd.cFileName); if ((hDll = LoadLibrary(szPluginPath)) == NULL) continue; LoadFilter = (LOADFILTERFCN)GetProcAddress(hDll, "LoadFilter"); if (NULL == LoadFilter) { FreeLibrary(hDll); hDll = NULL; continue; } if (!(*LoadFilter)(GetFcnPtrSvc)) { FreeLibrary(hDll); hDll = NULL; } if (hDll != NULL) { hDllPlugins = (HINSTANCE *)realloc((void *)hDllPlugins, (iDllPlugins+1)*sizeof(HINSTANCE)); hDllPlugins[iDllPlugins++] = hDll; } } while(FindNextFile(hFind, &fd)); FindClose(hFind); } } extern "C" int __declspec(dllexport) Load(void) { int i, k; mir_getLP(&pluginInfo); YAMN_STATUS = ID_STATUS_OFFLINE; // we get the Miranda Root Path PathToAbsoluteT( _T("."), szMirandaDir); // retrieve the current profile name CallService(MS_DB_GETPROFILENAMET, (WPARAM)SIZEOF(ProfileName), (LPARAM)ProfileName); //not to pass entire array to fcn TCHAR *fc = _tcsrchr(ProfileName, '.'); if ( fc != NULL ) *fc = 0; // we get the user path where our yamn-account.book.ini is stored from mirandaboot.ini file GetProfileDirectory(UserDirectory, SIZEOF(UserDirectory)); // Enumerate all the code pages available for the System Locale EnumSystemCodePages(EnumSystemCodePagesProc, CP_INSTALLED); CodePageNamesSupp = new _tcptable[CPLENSUPP]; for (i = 0, k = 0; i < CPLENALL; i++) { if (CodePageNamesAll[i].isValid) { CodePageNamesSupp[k] = CodePageNamesAll[i]; k++; } } // Registering YAMN as protocol PROTOCOLDESCRIPTOR pd = { PROTOCOLDESCRIPTOR_V3_SIZE }; pd.szName = YAMN_DBMODULE; pd.type = PROTOTYPE_VIRTUAL; CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd); InitializeCriticalSection(&AccountStatusCS); InitializeCriticalSection(&FileWritingCS); InitializeCriticalSection(&PluginRegCS); if (NULL == (NoWriterEV = CreateEvent(NULL, TRUE, TRUE, NULL))) return 1; if (NULL == (WriteToFileEV = CreateEvent(NULL, FALSE, FALSE, NULL))) return 1; if (NULL == (ExitEV = CreateEvent(NULL, TRUE, FALSE, NULL))) return 1; PosX = DBGetContactSettingDword(NULL, YAMN_DBMODULE, YAMN_DBPOSX, 0); PosY = DBGetContactSettingDword(NULL, YAMN_DBMODULE, YAMN_DBPOSY, 0); SizeX = DBGetContactSettingDword(NULL, YAMN_DBMODULE, YAMN_DBSIZEX, 800); SizeY = DBGetContactSettingDword(NULL, YAMN_DBMODULE, YAMN_DBSIZEY, 200); HeadPosX = DBGetContactSettingDword(NULL, YAMN_DBMODULE, YAMN_DBMSGPOSX, 0); HeadPosY = DBGetContactSettingDword(NULL, YAMN_DBMODULE, YAMN_DBMSGPOSY, 0); HeadSizeX = DBGetContactSettingDword(NULL, YAMN_DBMODULE, YAMN_DBMSGSIZEX, 690); HeadSizeY = DBGetContactSettingDword(NULL, YAMN_DBMODULE, YAMN_DBMSGSIZEY, 300); HeadSplitPos = DBGetContactSettingWord(NULL, YAMN_DBMODULE, YAMN_DBMSGPOSSPLIT, 250); optDateTime = DBGetContactSettingByte(NULL, YAMN_DBMODULE, YAMN_DBTIMEOPTIONS, optDateTime); // Create new window queues for broadcast messages YAMNVar.MessageWnds = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); YAMNVar.NewMailAccountWnd = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); YAMNVar.Shutdown = FALSE; hCurSplitNS = LoadCursor(NULL, IDC_SIZENS); hCurSplitWE = LoadCursor(NULL, IDC_SIZEWE); #ifdef _DEBUG InitDebug(); #endif CreateServiceFunctions(); SkinAddNewSoundEx(YAMN_NEWMAILSOUND, YAMN_DBMODULE, YAMN_NEWMAILSNDDESC); SkinAddNewSoundEx(YAMN_CONNECTFAILSOUND, YAMN_DBMODULE, YAMN_CONNECTFAILSNDDESC); HookEvents(); LoadIcons(); LoadPlugins(); InitVSApi(); HOTKEYDESC hkd = {0}; hkd.cbSize = sizeof(hkd); hkd.pszService = MS_YAMN_FORCECHECK; hkd.pszSection = YAMN_DBMODULE; hkd.pszDescription = LPGEN("Check mail"); hkd.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, VK_F11); Hotkey_Register(&hkd); //Create thread that will be executed every second if (!(SecTimer = SetTimer(NULL, 0, 1000, (TIMERPROC)TimerProc))) return 1; return 0; } ///////////////////////////////////////////////////////////////////////////////////////// static void UnloadPlugins() { for (int i = iDllPlugins-1;i>=0;i--) { if (FreeLibrary(hDllPlugins[i])) { hDllPlugins[i] = NULL; //for safety iDllPlugins --; } } if (hDllPlugins) { free((void *)hDllPlugins); hDllPlugins = NULL; } } extern "C" int __declspec(dllexport) Unload(void) { #ifdef _DEBUG UnInitDebug(); #endif DestroyCursor(hCurSplitNS); DestroyCursor(hCurSplitWE); CloseHandle(NoWriterEV); CloseHandle(WriteToFileEV); CloseHandle(ExitEV); FreeVSApi(); DeleteCriticalSection(&AccountStatusCS); DeleteCriticalSection(&FileWritingCS); DeleteCriticalSection(&PluginRegCS); UnhookEvents(); DestroyServiceFunctions(); UnloadPlugins(); delete [] CodePageNamesSupp; return 0; }