From: <ke...@us...> - 2008-08-17 03:11:35
|
Revision: 534 http://otlkcon.svn.sourceforge.net/otlkcon/?rev=534&view=rev Author: kervin Date: 2008-08-17 03:11:44 +0000 (Sun, 17 Aug 2008) Log Message: ----------- Adding util functions for DLL server support using in Milestone 3. Added Paths: ----------- trunk/otlkcon/otlkcon_utils.cpp Added: trunk/otlkcon/otlkcon_utils.cpp =================================================================== --- trunk/otlkcon/otlkcon_utils.cpp (rev 0) +++ trunk/otlkcon/otlkcon_utils.cpp 2008-08-17 03:11:44 UTC (rev 534) @@ -0,0 +1,559 @@ +/***************************************************************************** +Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Kervin L. Pierre + EMAIL: ot...@ad... + +This file is part of Otlkcon. + +Otlkcon is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +Otlkcon is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +Lesser GNU General Public License for more details. + +You should have received a copy of the Lesser GNU General Public License +along with Otlkcon; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*******************************************************************************/ + +#include <stdafx.h> +#include <vector> +#include <MsiQuery.h> + +#include <boost/xpressive/xpressive.hpp> + +extern int otlkcon_logToScreenEnabled; +extern int otlkcon_logToFileEnabled; +extern wchar_t otlkcon_logFile[MAX_PATH+1]; + +typedef BOOL (STDAPICALLTYPE FGETCOMPONENTPATH) + (LPSTR szComponent, + LPSTR szQualifier, + LPSTR szDllPath, + DWORD cchBufferSize, + BOOL fInstall); +typedef FGETCOMPONENTPATH FAR * LPFGETCOMPONENTPATH; + +HRESULT find_mapisvc(std::wstring *file); + +HRESULT merge_mapisvcinf(std::wstring inifile, + std::wstring mapisvcinf, + std::wstring mapisvcinf_bak); + +void print_options(int retVal, std::wstring str); + +void CALLBACK O_UtilEntryW(HWND hwnd, HINSTANCE hinst, + LPWSTR lpszCmdLine, int nCmdShow) +{ + int result = 0; + std::wstring currCmdLine = lpszCmdLine; + boost::xpressive::wsregex_token_iterator end; + boost::xpressive::wsregex cmdLineReg + = boost::xpressive::wsregex::compile( +L"((?:[^ \"']+)|(?:\"[^\"]*\\\\(?:.[^\"]*\\\\)*.[^\"]*\")|(?:\"[^\"]*\"))"); + boost::xpressive::wsregex removeQuoteReg + = boost::xpressive::wsregex::compile(L"^[\"]?(.*?)[\"]?$"); + + int tempSE = otlkcon_logToScreenEnabled; + otlkcon_logToScreenEnabled = 1; + int tempFE = otlkcon_logToFileEnabled; + otlkcon_logToFileEnabled = 1; + + int find_flag = 0; + int mapisvcinf_flag = 0; + int show_library_flag = 0; + int merge_mapisvcinf_flag = 0; + int logfile_flag = 0; + int help_flag = 0; + + std::wstring find_flag_arg = L""; + std::wstring mapisvcinf_flag_arg = L""; + std::wstring merge_mapisvcinf_flag_arg = L""; + std::wstring show_library_flag_arg = L""; + std::wstring logfile_flag_arg = L""; + std::wstring *prev_flag = NULL; + + for( boost::xpressive::wsregex_token_iterator + i(currCmdLine.begin(), currCmdLine.end(), cmdLineReg ); + i != end; ++i ) + { + std::wstring currArg = *i; + std::wstring unfoldStr = L"$1"; + currArg = regex_replace(currArg, removeQuoteReg, unfoldStr); + + //MessageBoxW(NULL, currArg.c_str(), NULL, MB_OK); + if( currArg == L"--find" ) + { + find_flag = 1; + prev_flag = &find_flag_arg; + } + else if( currArg == L"--mapisvcinf" ) + { + mapisvcinf_flag = 1; + prev_flag = &mapisvcinf_flag_arg; + } + else if( currArg == L"--logfile" ) + { + logfile_flag = 1; + prev_flag = &logfile_flag_arg; + } + else if( currArg == L"--merge-mapisvcinf" ) + { + merge_mapisvcinf_flag = 1; + prev_flag = &merge_mapisvcinf_flag_arg; + } + else if( currArg == L"--show-library" ) + { + show_library_flag = 1; + prev_flag = &show_library_flag_arg; + } + else if( currArg == L"--help" ) + { + help_flag = 1; + } + else + { + if( prev_flag == NULL ) + { + print_options(1, L"ERROR: unknown command argument." ); + } + prev_flag->assign( (currArg) ); + prev_flag = 0; + } + } + + // Setup the log file first if needed + if( logfile_flag == 1 ) + { + // log to a file + wcscpy_s(otlkcon_logFile,MAX_PATH+1, + logfile_flag_arg.c_str()); + otlkcon_logToFileEnabled = 1; + } + + if(help_flag == 1 ) + { + print_options(0, L"" ); + } + + std::wstring found_mapisvcinf_file = L""; + if( find_flag == 1 ) + { + if( find_flag_arg.length() == 0 ) + { + print_options(1, L"Required arg for --find is missing" ); + result = E_FAIL; + goto main_end; + } + else if( find_flag_arg == L"mapisvcinf" ) + { + if( find_mapisvc(&found_mapisvcinf_file) == S_OK ) + { + if( merge_mapisvcinf_flag == 0 ) + { + MessageBox(NULL, found_mapisvcinf_file.c_str(), L"MAPISvc.INF found", MB_OK); + } + mapisvcinf_flag_arg = found_mapisvcinf_file; + } + else + { + // Error condition + goto main_end; + } + } + else print_options(1, L"ERROR: Unknown option for --find flag." ); + } + + if( show_library_flag == 1 ) + { + HINSTANCE hinstStub = LoadLibraryW( OTLKCON_MSTORE_DLL_NAME ); + if( hinstStub == NULL ) + { + OTLKCON_LOG_PRINT_LAST_ERROR(); + OTLKCON_LOG_PRINTF( OTLKCON_LOG_LEVEL_INFO, OTLKCON_LOG_TARGET_ALL, + L"ERROR: Could not load the '%s' library\n", OTLKCON_MSTORE_DLL_NAME ); + result = E_FAIL; + } + } + + if( mapisvcinf_flag == 1 ) + { + if( mapisvcinf_flag_arg.length() == 0 ) + print_options(1, L"Required arg for --mapisvcinf is missing"); + } + + if( merge_mapisvcinf_flag == 1 ) + { + if( merge_mapisvcinf_flag_arg.length() == 0 ) + { + print_options(1, L"Required arg for --merge-mapisvcinf is missing"); + } + + // TODO: Save file in the format + "20060109-01.bak" + + // TODO: If the backup destination exists we should simply + // Try with another. eg "20060109-02.bak" + std::wstring bkFile = mapisvcinf_flag_arg + L".bak"; + if( mapisvcinf_flag_arg.length() > 0 ) + { + result = merge_mapisvcinf(merge_mapisvcinf_flag_arg, + mapisvcinf_flag_arg, bkFile); + } + else print_options(1, + L"No 'MapiSvc.inf' given. Use either '--find mapisvcinf' or '--mapisvcinf <filepath>'" ); + } + +main_end: + otlkcon_logToScreenEnabled = tempSE; + otlkcon_logToFileEnabled = tempFE; + return; +} + +void print_options(int retVal, std::wstring str) +{ + std::wostringstream buff; + + buff << L"Open Connector Groupware - [ http://openconnector.org/ ]" << std::endl << std::endl + << str << std::endl << std::endl + << L"ocpcon32.dll [--find mapisvcinf] [--mapisvcinf filename] [--merge-mapisvcinf filename]" << std::endl << std::endl + << L"--find - Find a configuration file. Currently only mapisvc.inf is supported." << std::endl + << L"--mapisvcinf - Specify the full mapisvc.inf for an operation" << std::endl + << L"--merge-mapisvcinf - Merge an INI file with MapiSvc.inf" << std::endl; + + MessageBoxW(NULL, buff.str().c_str(), L"Open Connector Groupware", MB_OK); + + OTLKCON_LOG_PRINTF( OTLKCON_LOG_LEVEL_INFO, + OTLKCON_LOG_TARGET_ALL|OTLKCON_LOG_FLAG_NO_DATE, + L"%s", buff.str().c_str() ); + + exit(retVal); +} + +// HrGetRegMultiSZValueA +// Get a REG_MULTI_SZ registry value - allocating memory using new to hold it. +void HrGetRegMultiSZValueA( + IN HKEY hKey, // the key. + IN LPCSTR lpszValue, // value name in key. + OUT LPVOID* lppData) // where to put the data. +{ + *lppData = NULL; + DWORD dwKeyType = NULL; + DWORD cb = NULL; + LONG lRet = 0; + + // Get its size + lRet = RegQueryValueExA( + hKey, + lpszValue, + NULL, + &dwKeyType, + NULL, + &cb); + + if (ERROR_SUCCESS == lRet && cb && REG_MULTI_SZ == dwKeyType) + { + *lppData = new BYTE[cb]; + + if (*lppData) + { + // Get the current value + lRet = RegQueryValueExA( + hKey, + lpszValue, + NULL, + &dwKeyType, + (unsigned char*)*lppData, + &cb); + + if (ERROR_SUCCESS != lRet) + { + delete[] *lppData; + *lppData = NULL; + } + } + } +} + +HRESULT find_mapisvc(std::wstring *file) +{ + HRESULT hRes = S_OK; + UINT uiRet = 0; + LONG lRet = 0; + BOOL bRet = true; + + char szMAPIDir[MAX_PATH+1] = {0}; + char szSystemDir[MAX_PATH+1] = {0}; + + // Get the system directory path + // (mapistub.dll and mapi32.dll reside here) + uiRet = GetSystemDirectoryA(szSystemDir, MAX_PATH); + if (uiRet > 0) + { + char szDLLPath[MAX_PATH+1] = {0}; + + hRes = sprintf_s(szDLLPath, MAX_PATH+1, "%s\\%s", + szSystemDir, "mapistub.dll"); + if (SUCCEEDED(hRes)) + { + LPFGETCOMPONENTPATH pfnFGetComponentPath = NULL; + + HMODULE hmodStub = 0; + HMODULE hmodMapi32 = 0; + + // Load mapistub.dll + hmodStub = LoadLibraryA(szDLLPath); + if (hmodStub) + { + // Get the address of FGetComponentPath from the mapistub + pfnFGetComponentPath = (LPFGETCOMPONENTPATH)GetProcAddress( + hmodStub, "FGetComponentPath"); + } + + // If we didn't get the address of FGetComponentPath + // try mapi32.dll + if (!pfnFGetComponentPath) + { + hRes = sprintf_s(szDLLPath, MAX_PATH+1, "%s\\%s", + szSystemDir, "mapi32.dll"); + if (SUCCEEDED(hRes)) + { + // Load mapi32.dll + hmodMapi32 = LoadLibraryA(szDLLPath); + if (hmodMapi32) + { + // Get the address of FGetComponentPath from mapi32 + pfnFGetComponentPath = (LPFGETCOMPONENTPATH)GetProcAddress( + hmodMapi32, "FGetComponentPath"); + } + } + } + if (pfnFGetComponentPath) + { + LPSTR szAppLCID = NULL; + LPSTR szOfficeLCID = NULL; + HKEY hMicrosoftOutlook = NULL; + + lRet = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + L"Software\\Clients\\Mail\\Microsoft Outlook", + NULL, + KEY_READ, + &hMicrosoftOutlook); + + if (ERROR_SUCCESS == lRet && hMicrosoftOutlook) + { + HrGetRegMultiSZValueA(hMicrosoftOutlook, "MSIApplicationLCID", (LPVOID*) &szAppLCID); + HrGetRegMultiSZValueA(hMicrosoftOutlook, "MSIOfficeLCID", (LPVOID*) &szOfficeLCID); + } + + if (szAppLCID) + { + bRet = pfnFGetComponentPath( + "{FF1D0740-D227-11D1-A4B0-006008AF820E}", szAppLCID, szMAPIDir, MAX_PATH, true); + } + if ((!bRet || szMAPIDir[0] == '\0') && szOfficeLCID) + { + bRet = pfnFGetComponentPath( + "{FF1D0740-D227-11D1-A4B0-006008AF820E}", szOfficeLCID, szMAPIDir, MAX_PATH, true); + } + if (!bRet || szMAPIDir[0] == '\0') + { + bRet = pfnFGetComponentPath( + "{FF1D0740-D227-11D1-A4B0-006008AF820E}", NULL, szMAPIDir, MAX_PATH, true); + } + + // We got the path to msmapi32.dll - need to strip it + if (bRet && szMAPIDir[0] != '\0') + { + LPSTR lpszSlash = NULL; + LPSTR lpszCur = szMAPIDir; + + for (lpszSlash = lpszCur; *lpszCur; lpszCur = lpszCur++) + { + if (*lpszCur == '\\') lpszSlash = lpszCur; + } + *lpszSlash = '\0'; + } + + delete[] szOfficeLCID; + delete[] szAppLCID; + if (hMicrosoftOutlook) RegCloseKey(hMicrosoftOutlook); + } + + // If FGetComponentPath returns FALSE or if + // it returned nothing, or if we never found an + // address of FGetComponentPath, then + // just default to the system directory + if (!bRet || szMAPIDir[0] == '\0') + { + hRes = sprintf_s( + szMAPIDir, MAX_PATH,"%s", szSystemDir); + } + + if (szMAPIDir[0] != '\0') + { + hRes = sprintf_s( + szMAPIDir, MAX_PATH, "%s\\%s", szMAPIDir, "MAPISVC.INF"); + } + + if (hmodMapi32) FreeLibrary(hmodMapi32); + if (hmodStub) FreeLibrary(hmodStub); + } + } + + wchar_t tempFile[MAX_PATH+1] = {0}; + swprintf_s(tempFile,MAX_PATH+1, L"%S", szMAPIDir); + file->assign(tempFile); + + return S_OK; +} + +// Given the full path to MAPISvc.INF and a INI file fragment, +// merge the two files into MAPISvc.INF after backing up the +// old file. +HRESULT merge_mapisvcinf( std::wstring inifile, + std::wstring mapisvcinf, + std::wstring mapisvcinf_bak ) +{ + LPWSTR szSectionBuff, szBuff, szBuff2, szValueBuff; + ULONG szBuffSize; + std::wstring valueTemp; + std::basic_string <wchar_t>::size_type i; + static const std::basic_string <wchar_t>::size_type npos = -1; + HRESULT result = S_OK; + + // One 2MB + szBuffSize = 1024 * 1024; + + OTLKCON_LOG_PRINTF( OTLKCON_LOG_LEVEL_INFO, OTLKCON_LOG_TARGET_ALL, + L" Merging '%s' with '%s'", inifile.c_str(), mapisvcinf.c_str() ); + + // If MapiSvc.Inf does not exist, create it + if((CopyFileW(inifile.c_str(),mapisvcinf.c_str(),true))) + { + std::wstring teststr = inifile + L" ( first Copy done ) "; + MessageBoxW(NULL, teststr.c_str(), NULL, MB_OK); + return S_OK; + } + + if ((CopyFileW(mapisvcinf.c_str(),mapisvcinf_bak.c_str(),false))==false) + { + //TODO: We should return specific error codes so the gui can relay + // The problem to the user. + + MessageBoxW(NULL, L"Second Copy fail", NULL, MB_OK ); + + //copy attempt failed + OTLKCON_LOG_PRINTF( OTLKCON_LOG_LEVEL_INFO, OTLKCON_LOG_TARGET_ALL, L"ochelper mergeini aborted- mapisvcinf file backup failed " ); + + return E_FAIL; + } + + if( PathFileExistsW( inifile.c_str() ) == FALSE ) + { + + MessageBoxW(NULL, L"Path doesn't exist", NULL, MB_OK ); + OTLKCON_LOG_PRINTF( OTLKCON_LOG_LEVEL_INFO, OTLKCON_LOG_TARGET_ALL, L"ochelper mergeini aborted- '%s' not found ", inifile.c_str() ); + + return E_FAIL; + } + + szBuff = (wchar_t *)calloc(szBuffSize, sizeof(wchar_t)); + szSectionBuff = szBuff; + szBuff2 = (wchar_t *)calloc(szBuffSize, sizeof(wchar_t)); + szValueBuff = szBuff2; + + // Get sectionnames from API and split it into array of strings + result = GetPrivateProfileSectionNamesW( szSectionBuff, + szBuffSize, inifile.c_str() ); + if( result == (szBuffSize - 2) ) + { + // TODO: The buffer was too small. Handle it. + DebugBreak(); + + return E_FAIL; + } + + //for each element in section name....go get stuff for section + while( wcslen( szSectionBuff ) ) + { + result = GetPrivateProfileSectionW( szSectionBuff, szValueBuff, + szBuffSize, inifile.c_str() ); + if( result == ( szBuffSize - 2 ) ) + { + // TODO: Buff too small. Handle it. + DebugBreak(); + + return E_FAIL; + } + + while( wcslen( szValueBuff ) ) + { + valueTemp = szValueBuff; + i = valueTemp.find( L"=" ); + if( i == npos ) + { + // TODO: '=' not found. Handle it. + DebugBreak(); + } + else + { + result = WritePrivateProfileStringW( szSectionBuff, + valueTemp.substr(0,i).c_str(), + valueTemp.substr(i+1).c_str(), + mapisvcinf.c_str() ); + } + + szValueBuff += wcslen( szValueBuff ) + 1; + } + + memset( szBuff2, szBuffSize, sizeof(wchar_t) ); + szValueBuff = szBuff2; + + // Get the next section name + szSectionBuff += wcslen( szSectionBuff ) + 1; + } + free( szBuff ); + free( szBuff2 ); + + return S_OK; +} + +//UINT __stdcall O_MSIInstall(MSIHANDLE hInstall) +//{ +// wchar_t custData [1024] = {0}; +// DWORD ulCustData = 1024; +// +// UINT gp = MsiGetPropertyW(hInstall, L"CustomActionData", +// custData, &ulCustData); +// +// O_UtilEntryW(0, 0, custData, 0); +// +// return 0; +//} + +HRESULT otlkcon_dumpbin(unsigned __int8 *lpBin, ULONG ulSize, std::wstring &dest) +{ + HRESULT result = S_OK; + std::wostringstream buff; + + for(ULONG i=0; i<ulSize; i++) + { + if( i % 16 == 0) + { + buff << std::endl; + } + + buff << std::hex << std::setw(2) + << std::setfill(L'0') << lpBin[i] << " "; + } + buff << std::endl; + + dest.assign( buff.str() ); + + return result; +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |