]> git.sesse.net Git - freerainbowtables/blobdiff - Client Applications/rcracki_mt/ChainWalkSet.cpp
backport rcracki_mt trunk from rcracki.sourceforge.net
[freerainbowtables] / Client Applications / rcracki_mt / ChainWalkSet.cpp
index b80b4ab60a3e0eacac6ecb431e0e37f5af93c2a2..48ca77547a0a0f6e28c0ff222eb15406ebb59b27 100644 (file)
-/*
- * 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");
-}
+/*\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
+               long 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