#include "stdafx.h" #include "Form1.h" #include #include #include #include using namespace SRInstallMGR; using namespace System; using namespace System::IO; TCHAR swordPath[MAX_PATH]; const char *stristr(const char *haystack, const char *needle){ // not mine - nicked this off the 'net if ( !*needle ) return haystack; for ( ; *haystack; ++haystack ){ if ( toupper(*haystack) == toupper(*needle) ){ const char *h, *n; for ( h = haystack, n = needle; *h && *n; ++h, ++n ){ if ( toupper(*h) != toupper(*n) )break; } if ( !*n ) return haystack; //return the start of the match } } return 0; } char *wstrtostr(const wchar_t *str) { // this came out of original SwordReader code - is there a better way? static char *c, *buffer = 0; if (buffer) delete [] buffer; buffer = c = new char[ wcslen(str) + 1 ]; while (*str) *c++ = (char)*str++; *c = 0; return buffer; } void copyconfs(WCHAR *confName) { TCHAR wszSrcFile[MAX_PATH]; WCHAR tszDestFile[MAX_PATH]; BYTE Buffer[10000]; HANDLE hSrc, hDest; DWORD dwNumRead, dwNumWritten; wcscpy_s(wszSrcFile, swordPath); wcscat_s(wszSrcFile, TEXT("mods.d\\")); wcscat_s(wszSrcFile, confName); wcscpy_s( tszDestFile, TEXT("mods.d\\")); wcscat_s( tszDestFile, confName); hSrc = CeCreateFile(wszSrcFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hSrc) { MessageBox::Show("Sorry, I'm struggling to open a file on your \ device.", "Process Failed", MessageBoxButtons::OK); Application::Exit(); } hDest = CreateFile(tszDestFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hDest) { MessageBox::Show("Sorry, I can't seem to write files to your PC.\ Do you have a mods.d directory where you put me?", "Process Failed", MessageBoxButtons::OK); // TODO - line break in MessageBox??? Application::Exit(); } if (CeReadFile(hSrc, &Buffer, sizeof(Buffer), &dwNumRead, NULL)) { if (!WriteFile(hDest, &Buffer, dwNumRead, &dwNumWritten, NULL)) { MessageBox::Show("Sorry, I can't seem to read the files on \ your mobile device.", "Process Failed", MessageBoxButtons::OK); Application::Exit(); } } else { MessageBox::Show("Sorry, I can't read the files on your mobile \ device.", "Process Failed", MessageBoxButtons::OK); Application::Exit(); } if (hSrc){ CeCloseHandle(hSrc); hSrc = NULL; } if (hDest){ CloseHandle (hDest); hDest = NULL; } } TCHAR* PrintDirectory(LPWSTR Path, UINT Indent){ // recurse through device from root DWORD foundCount; LPCE_FIND_DATA findDataArray; WCHAR searchPath[MAX_PATH]; wcscpy_s(searchPath, Path); wcscat_s(searchPath, L"*"); if(!CeFindAllFiles(searchPath, FAF_ATTRIBUTES | FAF_NAME, &foundCount, &findDataArray)) { MessageBox::Show("Sorry, I can't seem to open \ the files on your mobile device", "CeFindAllFiles Process Failed", MessageBoxButtons::OK); Application::Exit(); } if(!foundCount) return(NULL); for(UINT i = 0; i < foundCount; i++) { if(findDataArray[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // directory found WCHAR newPath[MAX_PATH]; wcscpy_s(newPath, Path); wcscat_s(newPath, findDataArray[i].cFileName); wcscat_s(newPath, L"\\"); PrintDirectory(newPath, Indent + 1); } else if ((stristr(wstrtostr(Path), "MODS.D"))){ // not directory - this is a file const char* modstr = stristr(wstrtostr(Path), "MODS.D"); wcscpy_s(swordPath, Path); int len = strlen (modstr); int swlen = wcslen (swordPath); while (len--) swlen--; swordPath[swlen] = 0; // global swordPath now set to CE sword dir /************************************************************************ // this refers to files on your mobile device, not your PC. // I don't want to do anything with files except when they are in your // MODS.D directory, so 'swordPath' at this point should be your sword // home directory+mods.d, so save it use return from stristr to truncate // I have assumed that mods.d occurs only once!!! There is one possible // additional instance (at least) .... // // TODO // note: have not checked for more than one installation: it is possible // for someone to have installed into several different locations - really! **************************************************************************/ copyconfs(findDataArray[i].cFileName); } // else if ((stristr(wstrtostr ...... } // for(UINT i = 0; ........ if (findDataArray) RapiFreeBuffer(findDataArray); return (swordPath); // swordPath is global ....... I don't like globals ... maybe a 'new' const wchar string would be better?? } void CopyOver (LPCWSTR sourceName, LPCWSTR destName) { HANDLE hSrc, hCeDest; BYTE Buffer[10000]; DWORD dwNumRead, dwNumWritten; hSrc = CreateFile(sourceName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hSrc) { MessageBox::Show("Sorry, I can't seem able to open source/host file on PC", "Process Failed", MessageBoxButtons::OK); Application::Exit(); } hCeDest = CeCreateFile(destName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hCeDest ) { MessageBox::Show("Sorry, I can't seem able to open destination file file on your mobile device for writing", "Process Failed", MessageBoxButtons::OK); Application::Exit(); } do { if (ReadFile(hSrc, &Buffer, sizeof(Buffer), &dwNumRead, NULL)) { if (!CeWriteFile(hCeDest, &Buffer, dwNumRead, &dwNumWritten, NULL)) { MessageBox::Show("Sorry, I can't seem able to open the file on your mobile device for writing", "Process Failed", MessageBoxButtons::OK); Application::Exit(); } } else { MessageBox::Show("Sorry, I can't seem able to open the source file file on your mobile device for writing", "Process Failed", MessageBoxButtons::OK); Application::Exit(); } } while (dwNumRead); if (hCeDest){ CeCloseHandle(hCeDest); hCeDest = NULL; } if (hSrc){ CloseHandle (hSrc); hSrc = NULL; } } bool fileExists(char *thisFile) { //char *thisFile = "sword.exe"; std::fstream fin; fin.open(thisFile, std::ios::in); if( fin.is_open()) { fin.close(); return true; } fin.close(); return false; } void getModulePath (LPCWSTR confName, char &outBuffer) { // each .conf file in mods.d comes here with name char longstr[10000]; const char *pathstr; char mPath[MAX_PATH]; char *modulePath = mPath; BOOL isopen = FALSE; HANDLE modFile; DWORD BytesToRead; DWORD BytesRead = 0; WCHAR namstr[MAX_PATH]; WCHAR* name = namstr; wcscpy (name, TEXT("mods.d\\")); wcscat (name, confName); BytesToRead = sizeof(longstr)-1; modFile = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == modFile) { MessageBox::Show("Sorry, I can't seem to read files in your mods.d directory. Do you have a mods.d directory where you put me?", "Process Failed", MessageBoxButtons::OK); Application::Exit(); } // read the entire .conf file into our buffer - biggest I know of // now is a 5k .conf, so I've gone for a 10,000 byte buffer .... isopen = ReadFile(modFile, &longstr, BytesToRead, &BytesRead, NULL); // TODO we ought to check for success 'if isopen' and do something if (modFile){ CloseHandle(modFile); modFile = NULL; } pathstr = stristr (longstr, "DataPath=."); if (!pathstr){ MessageBox::Show("Failed to make string match for DataPath=.", "Leaving now", MessageBoxButtons::OK); Application::Exit(); } pathstr+=10; // move pointer to end of 'DataPath=.' strcpy (modulePath, "");// this will need to be the swordPath int i = 0; int p = (strlen(modulePath)); p--; while (*(pathstr+i) != 10 && *(pathstr+i) != 13) { // some confs have cr/lf and some only lf (why?) *(modulePath+p++) = *(pathstr+i); i++; } // --p; // if we don't want trailing slash *(modulePath+p) = 0; // at end of trailing slash in pathstring // TODO - lexdicts are handled differently in pathing char *tmp = modulePath; while (*(tmp++))if (*tmp == 47) *tmp = 92; // change '/' into '\' tmp = &outBuffer; strcpy (tmp, modulePath); } void deleteCEFiles (LPCWSTR CEPath) { // delete all files in mobile device directory then delete directory TCHAR ThisFile[MAX_PATH]; DWORD foundCount; LPCE_FIND_DATA findDataArray; wcscpy_s(ThisFile, CEPath); wcscat_s(ThisFile, L"*"); if(!CeFindAllFiles(ThisFile, FAF_ATTRIBUTES | FAF_NAME, &foundCount, &findDataArray)) { // _tprintf( TEXT("*** CeFindAllFiles failed. ***\n")); return; // TODO needs error MessageBox here and bomb out } if(!foundCount) return; // TODO needs error MessageBox here and bomb out WCHAR newPath[MAX_PATH]; for(UINT i = 0; i < foundCount; i++) { wcscpy_s(newPath, CEPath); wcscat_s(newPath, findDataArray[i].cFileName); CeDeleteFile(newPath); } // for(UINT i = 0; i Clear();// Text = "*WORKING*"; n=0; hFile = FindFirstFile(TEXT("mods.d\\*.conf"), &FileInformation); if(hFile != INVALID_HANDLE_VALUE) { do { // each .conf file in mods.d comes here with name etc // START this pass storing .conf file name *NOT* ok while // debugging - but OK outside debugger also at end of debug // when testing with MessageBox - problem in debugger??? // TODO - nothing unless bug reports say otherwise!!!! int len = wcslen(FileInformation.cFileName) + 1; // how much space is needed TCHAR *newSpace = new WCHAR[len]; // allocate with new // copy to new space wcscpy_s (newSpace, len, FileInformation.cFileName); newConfs[n] = newSpace; // save pointer n++; // TODO don't forget to delete new items later // END this pass - *NOT ok* (see first pass) getModulePath (FileInformation.cFileName, *mPath); String^ ptr = System::Runtime::InteropServices::Marshal::PtrToStringAnsi((IntPtr)modulePath); // I don't have a clue how the above line works, but it does! // better method used in MessageBox below TODO ... change? if (Directory::Exists(ptr)) { // if there is no directory under 'modules' skip this strcat (modulePath, "*"); int len = strlen(modulePath)+1; wchar_t *wText = new wchar_t[len]; memset(wText,0,len); ::MultiByteToWideChar(CP_ACP, NULL, modulePath, -1, wText,len); modDir = FindFirstFile(wText, &modFileInformation); if(modDir == INVALID_HANDLE_VALUE){ MessageBox::Show("Sorry, I can't seem to read files \ from your newly downloaded module.", "Process Failed", MessageBoxButtons::OK); Application::Exit(); } len = wcslen (wText); len --; *(wText+len) = 0; len = strlen(modulePath); *(modulePath +len - 1) = 0; do { // copy each of module files onto mobile device followed by .conf // create the path on the mobile device here wcscpy_s (tszCEDestFile, swordPath); wcscat_s (tszCEDestFile, wText); // full path to create CeCreateDirectory(tszCEDestFile, 0); // TODO - should do a check for creation here // file copy will fail else wcscpy_s(wszSrcFile, wText); wcscat_s(wszSrcFile, modFileInformation.cFileName); char destMP[MAX_PATH]; char *destModPath = destMP; strcpy (destModPath, swordPathString); strcat (destModPath, modulePath); len = strlen(destModPath) + 1; wchar_t *wDestFile = new wchar_t[len]; memset(wDestFile,0,len); // does this need delete? // TODO check above ........ new wchar_t[ .... ::MultiByteToWideChar(CP_ACP, NULL, destModPath, -1, wDestFile,len); wcscpy_s( tszCEDestFile, wDestFile); wcscat_s( tszCEDestFile, modFileInformation.cFileName); if(!(modFileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { // directory found CopyOver (wszSrcFile, tszCEDestFile); } // if(!(modFileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY }while(FindNextFile(modDir, &modFileInformation) == TRUE); if (modDir){ FindClose (modDir); modDir = NULL; } // now copy over the module .conf file wcscpy_s (tszCEDestFile, swordPath); wcscat_s (tszCEDestFile, TEXT("mods.d\\")); wcscat_s (tszCEDestFile, FileInformation.cFileName); wcscpy_s (wszSrcFile, TEXT("mods.d\\")); wcscat_s (wszSrcFile, FileInformation.cFileName); CopyOver (wszSrcFile, tszCEDestFile); } // if (Directory::Exists(ptr delete ptr; }while(FindNextFile(hFile, &FileInformation) == TRUE); newConfs[n] = 0; } /* // debug only code // save this code - it shows WCHAR string in MessageBox n = -1; while (newConfs[n++]) { // Convert to a System::String // String ^systemstring = gcnew String((char *)newConfs[n]); // TODO note that the above shows exactly what showed in SwordReader // MessageBox when using renderText ....... REVISIT String ^systemstring = gcnew String(newConfs[n]); systemstring += " is the current module .conf file"; MessageBox::Show(systemstring, "This is the new .conf file", MessageBoxButtons::OK); delete systemstring;} // end debug code */ // removeModule (TEXT("phillips.conf")); // for debug int Old = 0; int New = 0; do { // loop through all .conf files. If one is missing from // the start, the user wants to delete this module bool moduleDeleted = TRUE; while (newConfs[New]){ // for each Old module if (!wcscmp (oldConfs[Old], newConfs[New++])) { moduleDeleted = FALSE; // this one is still there } } if (moduleDeleted) { // this one is missing after Install MGR removeModule (oldConfs[Old]); // so delete from mobile } New = 0; } while (oldConfs[++Old]); // keep going till all have been checked if (modDir){ FindClose (modDir); modDir = NULL; } // Close handles if (hFile){ FindClose(hFile); hFile = NULL; } CeRapiUninit(); // TODO delete the two Conf arrays // now remove all the files from the pc Directory::Delete( "mods.d", true ); Directory::Delete( "modules", true ); return (swordPathString); } // if ( (WaitForSingleObject(ri.heRapiInit ..... else { MessageBox::Show("Sorry, I could not connect to your mobile \ device.", "CeRapiInit failed", MessageBoxButtons::OK); CeRapiUninit(); Application::Exit(); } if ( CeRapiInit() != E_FAIL ) { } else { MessageBox::Show("Sorry, I could not connect to your mobile \ device", "CeRapiInit failed", MessageBoxButtons::OK); CeRapiUninit(); Application::Exit(); } } // if ( SUCCEEDED(CeRapiInitEx Application::Exit(); return(0); // can't get here - but avoids warning }