]> git.sesse.net Git - freerainbowtables/blobdiff - Client Applications/rcracki_mt/ChainWalkSet.cpp
Merge branch 'master' of git@gitorious.org:freerainbowtables-applications/freerainbow...
[freerainbowtables] / Client Applications / rcracki_mt / ChainWalkSet.cpp
index 84db65f028d00d4292c1cb276be83def82a0ef7a..b80b4ab60a3e0eacac6ecb431e0e37f5af93c2a2 100644 (file)
-/*\r
- * rcracki_mt is a multithreaded implementation and fork of the original \r
- * RainbowCrack\r
- *\r
- * Copyright (C) Zhu Shuanglei <shuanglei@hotmail.com>\r
- * Copyright Martin Westergaard Jørgensen <martinwj2005@gmail.com>\r
- * Copyright 2009, 2010 Daniël Niggebrugge <niggebrugge@fox-it.com>\r
- * Copyright 2009, 2010 James Nobis <frt@quelrod.net>\r
- *\r
- * This file is part of rcracki_mt.\r
- *\r
- * rcracki_mt is free software: you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation, either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * rcracki_mt is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with rcracki_mt.  If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-\r
-#if defined(_WIN32) && !defined(__GNUC__)\r
-       #pragma warning(disable : 4786)\r
-#endif\r
-\r
-#include "ChainWalkSet.h"\r
-\r
-CChainWalkSet::CChainWalkSet()\r
-{\r
-       m_sHashRoutineName   = "";\r
-       m_sPlainCharsetName  = "";\r
-       m_nPlainLenMin       = 0;\r
-       m_nPlainLenMax       = 0;\r
-       m_nRainbowTableIndex = 0;\r
-       m_nRainbowChainLen   = 0;\r
-       debug = false;\r
-       sPrecalcPathName     = "";\r
-       preCalcPart          = 0;\r
-}\r
-\r
-CChainWalkSet::~CChainWalkSet()\r
-{\r
-       DiscardAll();\r
-}\r
-\r
-void CChainWalkSet::DiscardAll()\r
-{\r
-       //printf("debug: discarding all walk...\n");\r
-\r
-       list<ChainWalk>::iterator it;\r
-       for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)\r
-               delete [] it->pIndexE;\r
-       m_lChainWalk.clear();\r
-}\r
-\r
-string CChainWalkSet::CheckOrRotatePreCalcFile()\r
-{\r
-       char sPreCalcFileName[255];\r
-\r
-       // 255 files limit to be sure\r
-       for (; preCalcPart < 255; preCalcPart++)\r
-       {\r
-               sprintf(sPreCalcFileName, "%s.%d", sPrecalcPathName.c_str(), preCalcPart);\r
-               string sReturnPreCalcPath(sPreCalcFileName);\r
-\r
-               unsigned int fileLen = 0;\r
-\r
-               FILE* file = fopen(sReturnPreCalcPath.c_str(), "ab");\r
-               if(file!=NULL)\r
-               {\r
-                       fileLen = GetFileLen(file);\r
-                       long unsigned int nextFileLen = fileLen + (sizeof(uint64) * (m_nRainbowChainLen-1));\r
-                       // Rotate to next file if we are going to pass 2GB filesize\r
-                       if (nextFileLen < ((unsigned)2 * 1024 * 1024 * 1024))\r
-                       {\r
-                               // We might want to vPrecalcFiles.push_back(sReturnPreCalcPath) if we just created this file\r
-                               // We don't as only newly generated chainwalksets will be stored to this new file, so we don't have to look there\r
-                               if (debug) printf("Debug: Using for precalc: %s\n", sReturnPreCalcPath.c_str());\r
-                               fclose(file);\r
-                               return sReturnPreCalcPath;\r
-                       }\r
-                       fclose(file);\r
-               }\r
-       }\r
-\r
-       return string("");\r
-}\r
-\r
-void CChainWalkSet::updateUsedPrecalcFiles()\r
-{\r
-       // we might also use this function to search a wildcard path of precalc files\r
-       vPrecalcFiles.clear();\r
-       char sPreCalcFileName[255];\r
-\r
-       int i;\r
-       // 255 files max\r
-       for (i = 0; i < 255; i++)\r
-       {\r
-               sprintf(sPreCalcFileName, "%s.%d", sPrecalcPathName.c_str(), i);\r
-               string sTryPreCalcPath(sPreCalcFileName);\r
-               FILE* file = fopen(sTryPreCalcPath.c_str(), "rb");\r
-               if(file!=NULL) {\r
-                       vPrecalcFiles.push_back(sTryPreCalcPath);\r
-                       fclose(file);\r
-               }\r
-               else {\r
-                       break;\r
-               }\r
-       }\r
-}\r
-\r
-void CChainWalkSet::removePrecalcFiles()\r
-{\r
-       if (debug) printf("Debug: Removing precalc files.\n");\r
-       updateUsedPrecalcFiles();\r
-       string sCurrentPrecalcPathName = "";\r
-       string sCurrentPrecalcIndexPathName = "";\r
-       \r
-       int i;\r
-       for (i = 0; i < (int)vPrecalcFiles.size(); i++)\r
-       {\r
-               sCurrentPrecalcPathName = vPrecalcFiles[i];\r
-               sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";\r
-\r
-               if (debug) printf("Debug: Removing precalc file: %s\n", sCurrentPrecalcPathName.c_str());\r
-\r
-               if (remove(sCurrentPrecalcPathName.c_str()) != 0)\r
-                       if (debug) printf("Debug: Failed removing precalc file: %s\n", sCurrentPrecalcPathName.c_str());\r
-\r
-               if (debug) printf("Debug: Removing precalc index file: %s\n", sCurrentPrecalcIndexPathName.c_str());\r
-\r
-               if (remove(sCurrentPrecalcIndexPathName.c_str()) != 0)\r
-                       if (debug) printf("Debug: Failed removing precalc index file: %s\n", sCurrentPrecalcIndexPathName.c_str());\r
-\r
-       }\r
-}\r
-\r
-bool CChainWalkSet::FindInFile(uint64* pIndexE, unsigned char* pHash, int nHashLen)\r
-{\r
-       int gotPrecalcOnLine = -1;\r
-       char precalculationLine[255];\r
-       sprintf(precalculationLine, "%s_%s#%d-%d_%d_%d:%s\n", m_sHashRoutineName.c_str(), m_sPlainCharsetName.c_str(), m_nPlainLenMin, m_nPlainLenMax, m_nRainbowTableIndex, m_nRainbowChainLen, HexToStr(pHash, nHashLen).c_str() );\r
-       string precalcString(precalculationLine);\r
-\r
-       string sCurrentPrecalcPathName = "";\r
-       string sCurrentPrecalcIndexPathName = "";\r
-       long unsigned int offset;\r
-\r
-       int i;\r
-       for (i = 0; i < (int)vPrecalcFiles.size() && gotPrecalcOnLine == -1; i++)\r
-       {\r
-               sCurrentPrecalcPathName = vPrecalcFiles[i];\r
-               sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";\r
-\r
-               offset = 0;\r
-\r
-               vector<string> precalcLines;\r
-               if (ReadLinesFromFile(sCurrentPrecalcIndexPathName.c_str(), precalcLines))\r
-               {\r
-                       int j;\r
-                       for (j = 0; j < (int)precalcLines.size(); j++)\r
-                       {\r
-                               if (precalcString.compare(0, precalcString.size()-1, precalcLines[j]) == 0)\r
-                               {\r
-                                       gotPrecalcOnLine = j;\r
-                                       break;\r
-                               }\r
-\r
-                               // Parse\r
-                               vector<string> vPart;\r
-                               if (SeperateString(precalcLines[j], "___:", vPart))\r
-                               {\r
-                                       // add to offset\r
-                                       offset += ((atoi(vPart[3].c_str())-1) * sizeof(uint64));\r
-                               }\r
-                               else {\r
-                                       // corrupt file\r
-                                       printf("Corrupted precalculation file!\n");\r
-                                       gotPrecalcOnLine = -1;\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       if (gotPrecalcOnLine > -1)\r
-       {\r
-               if (debug) printf("Debug: Reading pre calculations from file, line %d offset %lu\n", gotPrecalcOnLine, offset);\r
-               \r
-               FILE* fp = fopen(sCurrentPrecalcPathName.c_str(), "rb");\r
-\r
-               if (fp!=NULL) {\r
-                       fseek(fp, offset, SEEK_SET);\r
-\r
-                       // We should do some verification here, for example by recalculating the middle chain, to catch corrupted files\r
-                       if(fread(pIndexE, sizeof(uint64), (unsigned long)m_nRainbowChainLen-1, fp) != (unsigned long)m_nRainbowChainLen-1)\r
-                               printf("File read error.");\r
-                       fclose(fp);\r
-               }\r
-               else\r
-                       printf("Cannot open precalculation file %s.\n", sCurrentPrecalcPathName.c_str());\r
-\r
-               //printf("\npIndexE[0]: %s\n", uint64tostr(pIndexE[0]).c_str());\r
-               //printf("\npIndexE[nRainbowChainLen-2]: %s\n", uint64tostr(pIndexE[m_nRainbowChainLen-2]).c_str());\r
-\r
-               return true;\r
-       }\r
-\r
-       return false;\r
-}\r
-\r
-void CChainWalkSet::StoreToFile(uint64* pIndexE, unsigned char* pHash, int nHashLen)\r
-{\r
-       if (debug) printf("\nDebug: Storing precalc\n");\r
-       \r
-       string sCurrentPrecalcPathName = CheckOrRotatePreCalcFile();\r
-       string sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";\r
-\r
-       FILE* fp = fopen(sCurrentPrecalcPathName.c_str(), "ab");\r
-       if(fp!=NULL)\r
-       {\r
-               if(fwrite(pIndexE, sizeof(uint64), (unsigned long)m_nRainbowChainLen-1, fp) != (unsigned long)m_nRainbowChainLen-1)\r
-                       printf("File write error.");\r
-               else\r
-               {\r
-                       FILE* file = fopen(sCurrentPrecalcIndexPathName.c_str(), "a");\r
-                       if (file!=NULL)\r
-                       {\r
-                               char precalculationLine[255];\r
-                               sprintf(precalculationLine, "%s_%s#%d-%d_%d_%d:%s\n", m_sHashRoutineName.c_str(), m_sPlainCharsetName.c_str(), m_nPlainLenMin, m_nPlainLenMax, m_nRainbowTableIndex, m_nRainbowChainLen, HexToStr(pHash, nHashLen).c_str() );\r
-                               fputs (precalculationLine, file);\r
-                               fclose (file);\r
-                       }\r
-               }\r
-               fclose(fp);\r
-               }\r
-       else\r
-               printf("Cannot open precalculation file %s\n", sCurrentPrecalcPathName.c_str());\r
-}\r
-\r
-uint64* CChainWalkSet::RequestWalk(unsigned char* pHash, int nHashLen,\r
-                                                                  string sHashRoutineName,\r
-                                                                  string sPlainCharsetName, int nPlainLenMin, int nPlainLenMax, \r
-                                                                  int nRainbowTableIndex, \r
-                                                                  int nRainbowChainLen,\r
-                                                                  bool& fNewlyGenerated,\r
-                                                                  bool setDebug,\r
-                                                                  string sPrecalc)\r
-{\r
-       debug = setDebug;\r
-       sPrecalcPathName = sPrecalc;\r
-\r
-       if (   m_sHashRoutineName   != sHashRoutineName\r
-               || m_sPlainCharsetName  != sPlainCharsetName\r
-               || m_nPlainLenMin       != nPlainLenMin\r
-               || m_nPlainLenMax       != nPlainLenMax\r
-               || m_nRainbowTableIndex != nRainbowTableIndex\r
-               || m_nRainbowChainLen   != nRainbowChainLen)\r
-       {\r
-               DiscardAll();\r
-\r
-               m_sHashRoutineName   = sHashRoutineName;\r
-               m_sPlainCharsetName  = sPlainCharsetName;\r
-               m_nPlainLenMin       = nPlainLenMin;\r
-               m_nPlainLenMax       = nPlainLenMax;\r
-               m_nRainbowTableIndex = nRainbowTableIndex;\r
-               m_nRainbowChainLen   = nRainbowChainLen;\r
-\r
-               ChainWalk cw;\r
-               memcpy(cw.Hash, pHash, nHashLen);\r
-               cw.pIndexE = new uint64[nRainbowChainLen - 1];\r
-               m_lChainWalk.push_back(cw);\r
-\r
-               // Only update this list when we search through another rainbow table\r
-               updateUsedPrecalcFiles();\r
-\r
-               if (!FindInFile(cw.pIndexE, pHash, nHashLen))\r
-                       fNewlyGenerated = true;\r
-               else\r
-                       fNewlyGenerated = false;\r
-               return cw.pIndexE;\r
-       }\r
-\r
-       list<ChainWalk>::iterator it;\r
-       for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)\r
-       {\r
-               if (memcmp(it->Hash, pHash, nHashLen) == 0)\r
-               {\r
-                       fNewlyGenerated = false;\r
-                       return it->pIndexE;\r
-               }\r
-       }\r
-\r
-       ChainWalk cw;\r
-       memcpy(cw.Hash, pHash, nHashLen);\r
-       cw.pIndexE = new uint64[nRainbowChainLen - 1];\r
-       m_lChainWalk.push_back(cw);\r
-\r
-       if (!FindInFile(cw.pIndexE, pHash, nHashLen))\r
-                       fNewlyGenerated = true;\r
-               else\r
-                       fNewlyGenerated = false;\r
-       return cw.pIndexE;\r
-}\r
-\r
-void CChainWalkSet::DiscardWalk(uint64* pIndexE)\r
-{\r
-       list<ChainWalk>::iterator it;\r
-       for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)\r
-       {\r
-               if (it->pIndexE == pIndexE)\r
-               {\r
-                       delete it->pIndexE;\r
-                       m_lChainWalk.erase(it);\r
-                       return;\r
-               }\r
-       }\r
-\r
-       printf("debug: pIndexE not found\n");\r
-}\r
+/*
+ * rcracki_mt is a multithreaded implementation and fork of the original 
+ * RainbowCrack
+ *
+ * Copyright (C) Zhu Shuanglei <shuanglei@hotmail.com>
+ * Copyright Martin Westergaard Jørgensen <martinwj2005@gmail.com>
+ * Copyright 2009, 2010 Daniël Niggebrugge <niggebrugge@fox-it.com>
+ * Copyright 2009, 2010 James Nobis <frt@quelrod.net>
+ *
+ * This file is part of rcracki_mt.
+ *
+ * rcracki_mt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * rcracki_mt 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
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with rcracki_mt.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if defined(_WIN32) && !defined(__GNUC__)
+       #pragma warning(disable : 4786)
+#endif
+
+#include "ChainWalkSet.h"
+
+CChainWalkSet::CChainWalkSet()
+{
+       m_sHashRoutineName   = "";
+       m_sPlainCharsetName  = "";
+       m_nPlainLenMin       = 0;
+       m_nPlainLenMax       = 0;
+       m_nRainbowTableIndex = 0;
+       m_nRainbowChainLen   = 0;
+       debug = false;
+       sPrecalcPathName     = "";
+       preCalcPart          = 0;
+}
+
+CChainWalkSet::~CChainWalkSet()
+{
+       DiscardAll();
+}
+
+void CChainWalkSet::DiscardAll()
+{
+       //printf("debug: discarding all walk...\n");
+
+       list<ChainWalk>::iterator it;
+       for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)
+               delete [] it->pIndexE;
+       m_lChainWalk.clear();
+}
+
+string CChainWalkSet::CheckOrRotatePreCalcFile()
+{
+       char sPreCalcFileName[255];
+
+       // 255 files limit to be sure
+       for (; preCalcPart < 255; preCalcPart++)
+       {
+               sprintf(sPreCalcFileName, "%s.%d", sPrecalcPathName.c_str(), preCalcPart);
+               string sReturnPreCalcPath(sPreCalcFileName);
+
+               long fileLen = 0;
+
+               FILE* file = fopen(sReturnPreCalcPath.c_str(), "ab");
+               if(file!=NULL)
+               {
+                       fileLen = GetFileLen(file);
+                       long unsigned int nextFileLen = fileLen + (sizeof(uint64) * (m_nRainbowChainLen-1));
+                       // Rotate to next file if we are going to pass 2GB filesize
+                       if (nextFileLen < ((unsigned)2 * 1024 * 1024 * 1024))
+                       {
+                               // We might want to vPrecalcFiles.push_back(sReturnPreCalcPath) if we just created this file
+                               // We don't as only newly generated chainwalksets will be stored to this new file, so we don't have to look there
+                               if (debug) printf("Debug: Using for precalc: %s\n", sReturnPreCalcPath.c_str());
+                               fclose(file);
+                               return sReturnPreCalcPath;
+                       }
+                       fclose(file);
+               }
+       }
+
+       return string("");
+}
+
+void CChainWalkSet::updateUsedPrecalcFiles()
+{
+       // we might also use this function to search a wildcard path of precalc files
+       vPrecalcFiles.clear();
+       char sPreCalcFileName[255];
+
+       int i;
+       // 255 files max
+       for (i = 0; i < 255; i++)
+       {
+               sprintf(sPreCalcFileName, "%s.%d", sPrecalcPathName.c_str(), i);
+               string sTryPreCalcPath(sPreCalcFileName);
+               FILE* file = fopen(sTryPreCalcPath.c_str(), "rb");
+               if(file!=NULL) {
+                       vPrecalcFiles.push_back(sTryPreCalcPath);
+                       fclose(file);
+               }
+               else {
+                       break;
+               }
+       }
+}
+
+void CChainWalkSet::removePrecalcFiles()
+{
+       if (debug) printf("Debug: Removing precalc files.\n");
+       updateUsedPrecalcFiles();
+       string sCurrentPrecalcPathName = "";
+       string sCurrentPrecalcIndexPathName = "";
+       
+       int i;
+       for (i = 0; i < (int)vPrecalcFiles.size(); i++)
+       {
+               sCurrentPrecalcPathName = vPrecalcFiles[i];
+               sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";
+
+               if (debug) printf("Debug: Removing precalc file: %s\n", sCurrentPrecalcPathName.c_str());
+
+               if (remove(sCurrentPrecalcPathName.c_str()) != 0)
+                       if (debug) printf("Debug: Failed removing precalc file: %s\n", sCurrentPrecalcPathName.c_str());
+
+               if (debug) printf("Debug: Removing precalc index file: %s\n", sCurrentPrecalcIndexPathName.c_str());
+
+               if (remove(sCurrentPrecalcIndexPathName.c_str()) != 0)
+                       if (debug) printf("Debug: Failed removing precalc index file: %s\n", sCurrentPrecalcIndexPathName.c_str());
+
+       }
+}
+
+bool CChainWalkSet::FindInFile(uint64* pIndexE, unsigned char* pHash, int nHashLen)
+{
+       int gotPrecalcOnLine = -1;
+       char precalculationLine[255];
+       sprintf(precalculationLine, "%s_%s#%d-%d_%d_%d:%s\n", m_sHashRoutineName.c_str(), m_sPlainCharsetName.c_str(), m_nPlainLenMin, m_nPlainLenMax, m_nRainbowTableIndex, m_nRainbowChainLen, HexToStr(pHash, nHashLen).c_str() );
+       string precalcString(precalculationLine);
+
+       string sCurrentPrecalcPathName = "";
+       string sCurrentPrecalcIndexPathName = "";
+       long unsigned int offset;
+
+       int i;
+       for (i = 0; i < (int)vPrecalcFiles.size() && gotPrecalcOnLine == -1; i++)
+       {
+               sCurrentPrecalcPathName = vPrecalcFiles[i];
+               sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";
+
+               offset = 0;
+
+               vector<string> precalcLines;
+               if (ReadLinesFromFile(sCurrentPrecalcIndexPathName.c_str(), precalcLines))
+               {
+                       int j;
+                       for (j = 0; j < (int)precalcLines.size(); j++)
+                       {
+                               if (precalcString.compare(0, precalcString.size()-1, precalcLines[j]) == 0)
+                               {
+                                       gotPrecalcOnLine = j;
+                                       break;
+                               }
+
+                               // Parse
+                               vector<string> vPart;
+                               if (SeperateString(precalcLines[j], "___:", vPart))
+                               {
+                                       // add to offset
+                                       offset += ((atoi(vPart[3].c_str())-1) * sizeof(uint64));
+                               }
+                               else {
+                                       // corrupt file
+                                       printf("Corrupted precalculation file!\n");
+                                       gotPrecalcOnLine = -1;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (gotPrecalcOnLine > -1)
+       {
+               if (debug) printf("Debug: Reading pre calculations from file, line %d offset %lu\n", gotPrecalcOnLine, offset);
+               
+               FILE* fp = fopen(sCurrentPrecalcPathName.c_str(), "rb");
+
+               if (fp!=NULL) {
+                       fseek(fp, offset, SEEK_SET);
+
+                       // We should do some verification here, for example by recalculating the middle chain, to catch corrupted files
+                       if(fread(pIndexE, sizeof(uint64), (unsigned long)m_nRainbowChainLen-1, fp) != (unsigned long)m_nRainbowChainLen-1)
+                               printf("File read error.");
+                       fclose(fp);
+               }
+               else
+                       printf("Cannot open precalculation file %s.\n", sCurrentPrecalcPathName.c_str());
+
+               //printf("\npIndexE[0]: %s\n", uint64tostr(pIndexE[0]).c_str());
+               //printf("\npIndexE[nRainbowChainLen-2]: %s\n", uint64tostr(pIndexE[m_nRainbowChainLen-2]).c_str());
+
+               return true;
+       }
+
+       return false;
+}
+
+void CChainWalkSet::StoreToFile(uint64* pIndexE, unsigned char* pHash, int nHashLen)
+{
+       if (debug) printf("\nDebug: Storing precalc\n");
+       
+       string sCurrentPrecalcPathName = CheckOrRotatePreCalcFile();
+       string sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";
+
+       FILE* fp = fopen(sCurrentPrecalcPathName.c_str(), "ab");
+       if(fp!=NULL)
+       {
+               if(fwrite(pIndexE, sizeof(uint64), (unsigned long)m_nRainbowChainLen-1, fp) != (unsigned long)m_nRainbowChainLen-1)
+                       printf("File write error.");
+               else
+               {
+                       FILE* file = fopen(sCurrentPrecalcIndexPathName.c_str(), "a");
+                       if (file!=NULL)
+                       {
+                               char precalculationLine[255];
+                               sprintf(precalculationLine, "%s_%s#%d-%d_%d_%d:%s\n", m_sHashRoutineName.c_str(), m_sPlainCharsetName.c_str(), m_nPlainLenMin, m_nPlainLenMax, m_nRainbowTableIndex, m_nRainbowChainLen, HexToStr(pHash, nHashLen).c_str() );
+                               fputs (precalculationLine, file);
+                               fclose (file);
+                       }
+               }
+               fclose(fp);
+               }
+       else
+               printf("Cannot open precalculation file %s\n", sCurrentPrecalcPathName.c_str());
+}
+
+uint64* CChainWalkSet::RequestWalk(unsigned char* pHash, int nHashLen,
+                                                                  string sHashRoutineName,
+                                                                  string sPlainCharsetName, int nPlainLenMin, int nPlainLenMax, 
+                                                                  int nRainbowTableIndex, 
+                                                                  int nRainbowChainLen,
+                                                                  bool& fNewlyGenerated,
+                                                                  bool setDebug,
+                                                                  string sPrecalc)
+{
+       debug = setDebug;
+       sPrecalcPathName = sPrecalc;
+
+       if (   m_sHashRoutineName   != sHashRoutineName
+               || m_sPlainCharsetName  != sPlainCharsetName
+               || m_nPlainLenMin       != nPlainLenMin
+               || m_nPlainLenMax       != nPlainLenMax
+               || m_nRainbowTableIndex != nRainbowTableIndex
+               || m_nRainbowChainLen   != nRainbowChainLen)
+       {
+               DiscardAll();
+
+               m_sHashRoutineName   = sHashRoutineName;
+               m_sPlainCharsetName  = sPlainCharsetName;
+               m_nPlainLenMin       = nPlainLenMin;
+               m_nPlainLenMax       = nPlainLenMax;
+               m_nRainbowTableIndex = nRainbowTableIndex;
+               m_nRainbowChainLen   = nRainbowChainLen;
+
+               ChainWalk cw;
+               memcpy(cw.Hash, pHash, nHashLen);
+               cw.pIndexE = new uint64[nRainbowChainLen - 1];
+               m_lChainWalk.push_back(cw);
+
+               // Only update this list when we search through another rainbow table
+               updateUsedPrecalcFiles();
+
+               if (!FindInFile(cw.pIndexE, pHash, nHashLen))
+                       fNewlyGenerated = true;
+               else
+                       fNewlyGenerated = false;
+               return cw.pIndexE;
+       }
+
+       list<ChainWalk>::iterator it;
+       for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)
+       {
+               if (memcmp(it->Hash, pHash, nHashLen) == 0)
+               {
+                       fNewlyGenerated = false;
+                       return it->pIndexE;
+               }
+       }
+
+       ChainWalk cw;
+       memcpy(cw.Hash, pHash, nHashLen);
+       cw.pIndexE = new uint64[nRainbowChainLen - 1];
+       m_lChainWalk.push_back(cw);
+
+       if (!FindInFile(cw.pIndexE, pHash, nHashLen))
+                       fNewlyGenerated = true;
+               else
+                       fNewlyGenerated = false;
+       return cw.pIndexE;
+}
+
+void CChainWalkSet::DiscardWalk(uint64* pIndexE)
+{
+       list<ChainWalk>::iterator it;
+       for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)
+       {
+               if (it->pIndexE == pIndexE)
+               {
+                       delete it->pIndexE;
+                       m_lChainWalk.erase(it);
+                       return;
+               }
+       }
+
+       printf("debug: pIndexE not found\n");
+}