/* (C) 2003-2007 Willem Jan Hengeveld * Web: http://www.xs4all.nl/~itsme/ * http://wiki.xda-developers.com/ * * $Id: checkdll.cpp 1921 2008-07-31 17:08:31Z itsme $ */ // todo: add code to // - generate a itsutils certificate // - sign itsutils.dll // - upload certificate to the device // - unlock rapi for device. // // this may also be needed in some cases: // // // // // // // // // // #include #include #include #include #include "vectorutils.h" #include "stringutils.h" #include "filefunctions.h" #include "debug.h" #include "dllversion.h" #include "checkdll.h" #include "itsutils.h" // configuration variables std::string g_devicedllpath; // where to put itsutils.dll on the device. std::string g_devicelogpath; // where to put the itsutils.log file DWORD g_logtype= 0xFFFFFFFF; // non default log options // example config: // regutl -c HKCU\software\itsutils // regutl -s HKCU\software\itsutils ":devicedllpath=sz:\\storage card\\itsutils.dll" :logtype=dword:0 TCHAR *GetAppPath() { #ifdef WIN32 static TCHAR appname[1024]; if (!GetModuleFileName(NULL, appname, 1024)) return NULL; return appname; #else return "./test123"; #endif } BOOL ReadRegistryString(HKEY hRoot, const std::string& devicekey, const std::string& valname, std::string& strval) { HKEY hDevkey; LONG rc= RegOpenKeyEx(hRoot, ToTString(devicekey).c_str(), 0, KEY_READ, &hDevkey); if (rc) { //debug("rdstr-RegOpenKeyEx(%s): ERROR %08lx\n", devicekey.c_str(), rc); return FALSE; } DWORD valtype=0; DWORD maxsize=0; rc= RegQueryValueEx(hDevkey, ToTString(valname).c_str(), NULL, &valtype, NULL, &maxsize); if (rc==0 && maxsize==0) { strval.erase(); RegCloseKey(hDevkey); return TRUE; } if (rc!=0 && rc!=ERROR_MORE_DATA) { //debug("RegQueryValueEx('%s', '%s', string(%d)): ERROR %08lx\n", devicekey.c_str(), valname.c_str(), maxlen, rc); RegCloseKey(hDevkey); return FALSE; } ByteVector data; data.resize(maxsize+2); rc= RegQueryValueEx(hDevkey, ToTString(valname).c_str(), NULL, &valtype, &data[0], &maxsize); if (rc!=0) { //debug("RegQueryValueEx('%s', '%s', string(%d)): ERROR %08lx\n", devicekey.c_str(), valname.c_str(), maxlen, rc); RegCloseKey(hDevkey); return FALSE; } strval= ToString((TCHAR*)&data[0]); RegCloseKey(hDevkey); return TRUE; } BOOL ReadRegistryDword(HKEY hRoot, const std::string& devicekey, const std::string& valname, DWORD *pvalue) { HKEY hDevkey; LONG rc= RegOpenKeyEx(hRoot, ToTString(devicekey).c_str(), 0, KEY_READ, &hDevkey); if (rc) { //debug("rddw-RegOpenKeyEx(%s): ERROR %08lx\n", devicekey.c_str(), rc); return FALSE; } DWORD valtype=0; DWORD maxsize= sizeof(DWORD); rc= RegQueryValueEx(hDevkey, ToTString(valname).c_str(), NULL, &valtype, (LPBYTE)pvalue, &maxsize); if (rc) { //debug("RegQueryValueEx('%s', '%s', DWORD): ERROR %08lx\n", devicekey.c_str(), valname.c_str(), rc); RegCloseKey(hDevkey); return FALSE; } RegCloseKey(hDevkey); return TRUE; } void read_itsutils_config() { const std::string itsutilsregpath= "Software\\itsutils"; if (!ReadRegistryString(HKEY_CURRENT_USER, itsutilsregpath, "devicedllpath", g_devicedllpath)) g_devicedllpath= "\\windows\\itsutils.dll"; if (!ReadRegistryString(HKEY_CURRENT_USER, itsutilsregpath, "devicelogpath", g_devicelogpath)) g_devicelogpath= ""; if (!ReadRegistryDword(HKEY_CURRENT_USER, itsutilsregpath, "logtype", &g_logtype)) g_logtype= 0xFFFFFFFF; } bool CeFileExists(const std::tstring& name) { DWORD dwAttr = CeGetFileAttributes( ToWString(name).c_str() ); if (0xFFFFFFFF == dwAttr) return false; return true; } bool CeCopyFileToDevice(const std::tstring& srcfile, const std::tstring& dstfile, bool bOverwrite) { WIN32_FIND_DATA wfd; HANDLE hFind = FindFirstFile( srcfile.c_str(), &wfd); if (INVALID_HANDLE_VALUE == hFind) { error("Source/host file does not exist '%hs'\n", srcfile.c_str()); return false; } FindClose( hFind); if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { error("Source/host file specifies a directory '%hs'\n", srcfile.c_str()); return false; } std::tstring dstname= dstfile; bool bExists= false; DWORD dwAttr = CeGetFileAttributes( ToWString(dstname).c_str()); if (0xFFFFFFFF != dwAttr) { if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) { dstname += _T("\\"); dstname += wfd.cFileName; dwAttr = CeGetFileAttributes( ToWString(dstname).c_str()); // File already exists. -> true // dstname is directory -> false ( meaning something like \windows\dllname.dll is a directory ) // TODO: fix ambigous if .. if else if ((dwAttr != 0xFFFFFFFF)) { if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) { debug("ERROR: CeCopyFileToDevice to directory: %ls\n", dstname.c_str()); return false; } else bExists= true; } else bExists= false; } else bExists= true; } if (!bOverwrite && bExists) { debug("NOTE: CeCopyFileToDevice not overwriting file %ls\n", dstname.c_str()); return true; } HANDLE hSrc = CreateFile( srcfile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hSrc) { error("Unable to open source/host file '%hs'", srcfile.c_str()); return false; } HANDLE hDest = CeCreateFile( ToWString(dstname).c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hDest ) { ceerror("Unable to open WinCE file '%hs'", dstname.c_str()); return false; } debug("Copying %hs to WCE:%ls\n", srcfile.c_str(), ToWString(dstname).c_str()); ByteVector buffer; buffer.resize(32768); DWORD dwNumRead; do { if (ReadFile( hSrc, vectorptr(buffer), (DWORD)buffer.size(), &dwNumRead, NULL)) { DWORD dwNumWritten; if (!CeWriteFile( hDest, vectorptr(buffer), dwNumRead, &dwNumWritten, NULL)) { ceerror("Error !!! Writing WinCE file"); CeCloseHandle( hDest); CloseHandle (hSrc); return false; } } else { error("Error !!! Reading source file"); CeCloseHandle( hDest); CloseHandle (hSrc); return false; } } while (dwNumRead); CeCloseHandle( hDest); CloseHandle (hSrc); return true; } HRESULT ItsutilsInvoke(const WCHAR *method, DWORD insize, BYTE *inbuf, DWORD *poutsize, BYTE **outbuf) { return CeRapiInvoke(ToWString(g_devicedllpath).c_str(), method, insize, inbuf, poutsize, outbuf, NULL, 0); } void CheckITSDll() { if (FAILED(CeRapiInit())) { error("CeRapiInit failed\n"); exit(1); } std::tstring approot= GetAppPath(); approot.resize(approot.find_last_of('\\')); #if 0 if (!CeFileExists(_T("\\Windows\\toolhelp.dll"))) { if (!CeCopyFileToDevice(approot+_T("\\toolhelp.dll"), _T("\\windows"))) debug("probably you need to manually copy toolhelp.dll to your device\n"); } #endif read_itsutils_config(); DWORD insize= 0; ByteVector indata; GetVersionParams *inbuf=NULL; if (g_logtype != 0xFFFFFFFF) { insize= sizeof(GetVersionParams)+g_devicelogpath.size(); indata.resize(insize); inbuf= reinterpret_cast(&indata[0]); inbuf->logtype= g_logtype; strcpy(inbuf->szLogfile, g_devicelogpath.c_str()); //debug("setting itsutils config(%08lx,%08lx): %d '%s'\n", insize, inbuf, g_logtype, g_devicelogpath.c_str()); } DWORD outsize=0; HRESULT res= ItsutilsInvoke(L"ITGetVersion", insize, (BYTE*)inbuf, &outsize, NULL); // E_FAIL -> itsutils.dll is missing, or execute denied by policy if (res==E_FAIL && CeFileExists(ToTString(g_devicedllpath).c_str())) { debug("ERROR loading itsutils.dll - probably denied by policy restriction\n"); exit(1); } if (res==0x80072745 || res==0x80072746) { error(res, "ItsutilsInvoke(%s)", g_devicedllpath.c_str()); debug("\nplease reboot your device, or restart activesync\n"); exit(1); } if (res!=ITSDLL_VERSION) { if (!CeCopyFileToDevice(approot+_T("\\itsutils.dll"), ToTString(g_devicedllpath), true)) exit(1); res= ItsutilsInvoke(L"ITGetVersion", insize, (BYTE*)inbuf, &outsize, NULL); if (res==E_FAIL && CeFileExists(ToTString(g_devicedllpath).c_str())) { debug("ERROR loading itsutils.dll - probably denied by policy restriction\n"); exit(1); } } if (res!=ITSDLL_VERSION) { debug("Could not update itsutils.dll to the current version, maybe it is inuse?\n"); debug("try restarting your device, or restart activesync\n"); debug("or maybe your device is application-locked.\n"); exit(1); } }