Perhaps i spoke too soon :p

Ask for Help on Using the Language With Memory Hacking Software

Moderators: g3nuin3, SpeedWing, WhiteHat, mezzo

Perhaps i spoke too soon :p

Postby g3nuin3 » Wed Jan 10, 2007 12:29 am

Ok well See i thought i won, but seems im missing something..I wrote code that successfully reallocated the structure for the thread function but when it came to re-writing the DirSearch function i compile fine but crash on run..time ran out for me and i had to go to work so i leave you with the first code that demonstrated it working, then the SearchDir modified but crashes...will wait for the answer when i get back home later tonight..if not, ill give it another go.

HEre is the working test code
Code: Select all
struct DIRINFO{
      char *diPath;
      char *diFile;
      int isSubDirSearch;
      };   //structure to hold information for the SearchDir function


void DirThread()
{
   Clear();
   //Allocating a pointer to the structure for later reallocating it.
   DIRINFO *dirInfo = Malloc(sizeof(DIRINFO));
   //if(dirInfo == NULL){ return;}
   
   HANDLE hThread = CreateThread( "RanThread", (DWORD)dirInfo);
   if(!hThread){
      CloseHandle(hThread);
      return;
   }
   CloseHandle(hThread);
   return;
   
}
DWORD RanThread( DWORD dwParam )
{
   //ReAllocate the structure we allocated earlier.
   DIRINFO *dInfo = ReAlloc(&dwParam,sizeof(DIRINFO));
   dInfo->diPath = "C:\\";
   dInfo->diFile = "*.mp3";
   dInfo->isSubDirSearch = 0;
   
   PrintF("Info on dirInfo:  diInfo->diPath = %s , diInfo->diFile = %s, diInfo.Subs = %i",dInfo->diPath, dInfo->diFile, dInfo->isSubDirSearch);
   return 0;
}

VOID On_HK_0()
{
   DirThread();
}

It can be cleaned up and fixed to work better, but i only have a couple of hours between morning and work :(

And here is the modified for searchdir that compiles but crashes.
Code: Select all
struct DIRINFO{
      char *diPath;
      char *diFile;
      int isSubDirSearch;
      };   //structure to hold information for the SearchDir function


void DirThread()
{
   Clear();
   //Allocating a pointer to the structure for later reallocating it.
   DIRINFO *dirInfo = Malloc(sizeof(DIRINFO));
   //if(dirInfo == NULL){ return;}
   
   HANDLE hThread = CreateThread( "RanThread", (DWORD)dirInfo);
   if(!hThread){
      CloseHandle(hThread);
      return;
   }
   CloseHandle(hThread);
   return;
   
}

DWORD RanThread( DWORD dwParam )
{
   //ReAllocate the structure we allocated earlier.
   DIRINFO *dInfo = ReAlloc(&dwParam,sizeof(DIRINFO));
   dInfo->diPath = "C:\\";
   dInfo->diFile = "*.mp3";
   dInfo->isSubDirSearch = 0;
   //Now we pass the newly reallocated structure filled in to modified SearchDir.
   int i = SearchDir(dInfo);
   
   return 0;
}
   
INT SearchDir( DIRINFO *SInfo)
{
//Reaching near the end i realized it would have been better to create a new copy of the structure so as to not modify the one passed
//But thats for YOU to do!
   CHAR szFinal[MAX_PATH];
   SNPrintF( szFinal, MAX_PATH, "%s%s", SInfo->diPath, SInfo->diFile);
   
   WIN32_FIND_DATA wfdFind;
   
   INT iFound = 0;
   
   HANDLE hFind = FindFirstFile(szFinal, &wfdFind);
   //if handle is not invalid continue
   if( (DWORD)hFind != (DWORD)INVALID_HANDLE_VALUE)
   {
      while(hFind)
      {
         if( StrCmp(wfdFind.cFileName, ".") != 0 && StrCmp( wfdFind.cFileName, "..") != 0 )
         {
            if((wfdFind.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
            {
               iFound++;
               
               char szFile[MAX_PATH];
               SNPrintF(szFile, MAX_PATH, "%s%s", SInfo->diPath, wfdFind.cFileName);
               PrintF("%s", szFile );
            }
         }
         //Get Next File
         if(!FindNextFile(hFind, &wfdFind) )
         {
            FindClose(hFind);
            hFind = NULL;
            break;
         }
      }
   }
   
   if( SInfo->isSubDirSearch == 0 ) {return iFound;}
   
    SNPrintF( szFinal, MAX_PATH, "%s*", SInfo->diPath);
    hFind = FindFirstFile( szFinal, &wfdFind );
    if ( (DWORD)hFind != (DWORD)INVALID_HANDLE_VALUE ) {
        while ( hFind ) {
            if ( StrCmp( wfdFind.cFileName, "." ) != 0 && StrCmp( wfdFind.cFileName, ".." ) != 0 ) {
                // This time we only care about directories
                if ( wfdFind.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
                    // Recompile the string and pass it right back to this function in a
                    //  recursive call.
                    CHAR szDir[MAX_PATH];
                    SNPrintF( szDir, MAX_PATH, "%s%s\\", SInfo->diPath, wfdFind.cFileName );
                    //PrintF( "%s", szDir );

                    // Tricky part here. Gotta modify the structure abit to accomodate the subdir variable.
                    // I went through two methods but i will choose this one >.<
                    SInfo->isSubDirSearch--;
                    iFound += SearchDir( SInfo );
                }
            }

            // Get the next file.
            if ( !FindNextFile( hFind, &wfdFind ) ) {
                FindClose( hFind );
                hFind = NULL;
                break;
            }
        }
    }   // hFind != INVALID_HANDLE_VALUE

    // We are done, and iFound contains the total matching files.
    return iFound;
}
   
   
   
   

   
VOID On_HK_0()
{
   DirThread();
}
   


I didnt realize the function used recursion..poo me.
g3nuin3
Acker
 
Posts: 96
Joined: Tue Jul 18, 2006 10:53 am

Postby L. Spiro » Wed Jan 10, 2007 10:19 am

(For those who haven’t been following the forum in hardcore mode, this is in reference to my Code Submissions topic regarding the demo SearchDir() function. I mentioned that it is possible to take it off the main thread and run it on its own thread, but left that up to the users as a challenge.)





Conceptually you are almost correct.
But obviously if you are not 100% correct on the concept you won’t be 100% correct on the implementation, and that is what is causing your crashes.

SearchDir() itself does not need to be modified, and as you found it is in fact very difficult to modify because it is recursive.
So if you pass it your structure pointer you have a lot of work to do to make sure the recursive calls don’t overwrite the data in the structure (meaning you would have to make a new structure each time and pass that).


Also, there is no reason to ReAlloc() the structure in RanThread().
dwParam is already a pointer to a valid structure of DIRINFO (valid in terms of size of memory allocated; obviously the paths have not been set yet).



I will post the solution and you can compare and see how things are different.
But not to worry, because I will also post yet another challenge with it.




I will post it here instead of there, though, because others may want to try the challenge before looking in this thread.




Code: Select all
// To add threading capabilities to SearchDir(), we need a wrapper function
//  that is compatible with the CreateThread() function.
// The wrapper function will accept a pointer to a structure that we are
//  about to define.
struct MHS_SEARCHDIRPARMS {
    const CHAR * pcPath;        // Path to search.
    const CHAR * pcFile;        // File mask.
    INT iSubDirSearchDepth;     // Search depth.
};

// Does that structure look familiar?  Its members are the parameters we need
//  to get into SearchDir().

// Now create a function that accepts this structure as its only parameter.
// Having one parameter of 4 bytes in size makes this function compatible
//  with CreateThread() (though any function can be called by CreateThread(),
//  it may have garbage in its parameters if not used correctly).
// Note that this is really just a shortcut.  Normally we would create this
//  function with a DWORD parameter and cast it to a MHS_SEARCHDIRPARMS *
//  inside the function, but this shortcut works the same and is faster too.
INT SearchDir_SecondThread( MHS_SEARCHDIRPARMS * psdpParms ) {
    // Our only objective here is to call SearchDir() with the correct
    //  parameters, however we have one other task to do here.

    // psdpParms is a pointer that was created by Malloc(), and it was not
    //  freed with Free() because our main thread wants to make sure it is
    //  alive long enough for this thread to use it (main thread below).
    // As a result, the main thread leaves it up to us to call Free() on
    //  this pointer.

    // But first, get the actual result.
    INT iRet = SearchDir( psdpParms->pcPath,
        psdpParms->pcFile,
        psdpParms->iSubDirSearchDepth );

    // Getting the result is that easy!
    // We only needed a pointer to the MHS_SEARCHDIRPARMS object, and inside that
    //  object we had all the other parameters we needed for the call to SearchDir.


    // But now we have to free the psdpParms object, so do it.
    Free( psdpParms->pcPath );  // Created with StrDup(), so Free() it.
    Free( psdpParms->pcFile );  // Created with StrDup(), so Free() it.
    Free( psdpParms );

    // Pass back the value.
    // The main thread is not waiting for this thread to finish, so it can not
    //  actually get this value, but it is proper to return it anyway.
    return iRet;
}



// Finally, this is called by the main thread to start the second thread with the
//  correct parameters.
// It has the same paremeter list as SearchDir()!
INT SearchDir_MainThread( const CHAR * pcPath, const CHAR * pcFile, INT iSubDirSearchDepth ) {
    // This function is quite simple.
    // First, make an object that can hold these parameters.
    MHS_SEARCHDIRPARMS * psdpParms = Malloc( sizeof( MHS_SEARCHDIRPARMS ) );
    if ( (LPVOID)psdpParms == NULL ) { return -1; }

    // If that worked, copy the strings to a place where they will not be
    //  removed from memory while the second thread is working.
    psdpParms->pcPath = StrDup( pcPath );
    psdpParms->pcFile = StrDup( pcFile );
    psdpParms->iSubDirSearchDepth = iSubDirSearchDepth;

    // Call the second thread with the pointer to this structure as its parameter.
    HANDLE hThread = CreateThread( "SearchDir_SecondThread", (DWORD)psdpParms );

    // If it failed, delete the structure ourselves.
    if ( !hThread ) {
        Free( psdpParms->pcPath );  // Created with StrDup(), so Free() it.
        Free( psdpParms->pcFile );  // Created with StrDup(), so Free() it.
        Free( psdpParms );

        // No need to call CloseHandle() on a NULL handle.
        return -1;
    }

    // Coming here means the second thread is in motion, so let it delete
    //  the structure on its own when it is done.
    // Our work here is done.
    // Close our handle on the thread and get out of here.

    CloseHandle( hThread ); // This does not stop the second thread.  It just
                            //  releases our resources.

    PrintF( "Main thread closing." );
    // 1 for success, -1 for error.
    return 1;
}


// Our version of the standard StrDup() function.
// This will be added to the API in the next release!
CHAR * StrDup( const CHAR * pcString ) {
    INT iLength = StrLen( pcString ) + 1;
    CHAR * pcThis = Malloc( iLength );
    if ( !pcThis ) { return NULL; }
    // Because we used Malloc() here, the returned pointer will
    //  need to be deleted with Free() when it is done being used.
    StrCpy( pcThis, pcString );
    return pcThis;
}

This code can be copied and pasted directly under the original SearchDir() function posted in Code Submissions.


Now SearchDir() takes the same parameters and our main-threaded function takes those same parameters too.
So we can call either function easily. Calling SearchDir() will run on the main thread while calling SearchDir_MainThread() will run SearchDir() on another thread.
Note that calling SearchDir_MainThread() will not return the total number of files found, however.


I also had to write my own version of the standard C library StrDup() function, which will be officially part of the API next release.



To call this:

Code: Select all
VOID On_HK_0( DWORD dwP1, DWORD dwP2 ) {
    Clear();
    SearchDir_MainThread( "C:\\", "*.mp3", 3 );
    SearchDir_MainThread( "D:\\", "*.mp3", 3 );
}


Two threads will be started here, both running at the same time, printing results as they find them.
This is unlike before where it would scan the C: drive and then scan the D:.





Now you will find that MHS.exe does not hang while it is searching (although it becomes slow if lots of results are being printed).
However, you can’t recompile the code until the searches are done!


Next challenge: add a Cancel function to stop all SearchDir() searches.
The cancel feature can be as simple as a button press or as complicated as displaying a dialog with a Cancel button.

Some modifications to SearchDir() will be needed this time.


L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby hunter » Fri Jan 12, 2007 9:08 pm

Heres my solution to the challenge...
It has two hotkey functions. HK_0 starts the search thread and HK1 stops it.

Having tested it many times, this code is able to search through my 250gb hdd for all mp3s without crashing or freezing up. I think the performance could be improved with the use of regex, so that the DirSearchR don't have to scan the folder twice. Overall the performance of this code is acceptable.

The only major bottleneck is the MHS console. When outputting thousand lines or more of text to the MHS console, MHS would freeze almost to death untill every line has been outputted. It would be nice if we could open up a real dos console for the output.

Code: Select all
struct MHS_SEARCHDIRPARMS {
    const CHAR * diPath;        // Path to search.
    const CHAR * diFile;        // File mask.
    INT isSubDirSearch;     // Search depth.
};

enum FILETYPE {TYPE_FILE,TYPE_DIRECTORY};

struct MYFILE
{
   const char *path;
   const char *name;
   int type; //FILETYPE
};

//some variables used for thread signal
bool StopThread = false;
bool ThreadIdle = true;


//my own ReAlloc function, unused
void *MyReAlloc(const void *p, int oldsize, int newsize)
{
   void *ptr = Malloc(newsize);
   if(oldsize > 0) MemCpy(ptr,p,oldsize);
   Free(p);
   return ptr;
}

int AddToList(const MYFILE *file, MYFILE **List, int max, int count)
{
   if(count < max)
      List[count] = file;
   else return count;
   
   //PrintF("AddList - %s",List[count]->name);
   return count+1;
}

//grab an array of files in the current folder
//and return the number of files
int FileList(MHS_SEARCHDIRPARMS *dir,MYFILE **List, int count, int max)
{
   MYFILE *f = 0;
   WIN32_FIND_DATA fd;
   
   //PrintF("FileList %s%s",dir->diPath,dir->diFile);
   //PrintF("FileList-count %i",count);
   
   char *path = Malloc(StrLen(dir->diPath) + StrLen(dir->diFile) + 1);
   StrCpy(path,dir->diPath);
   StrCat(path,dir->diFile);
   
   HANDLE h = FindFirstFile(path,&fd);
   Free(path);
   if(h == INVALID_HANDLE_VALUE){
      return count;
   }
      
   if(!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
   {
      //PrintF("adding new file1 - %i",count);
      f = Malloc(sizeof(MYFILE));
      f->path = StrDup(dir->diPath);
      f->name = StrDup(fd.cFileName);
      f->type = TYPE_FILE;
      count = AddToList(f,List,max,count);
      
   }      
   else
   {
      if(StrCmp(fd.cFileName,".") != 0 && StrCmp(fd.cFileName,"..") != 0)
      {
         f = Malloc(sizeof(MYFILE));
         f->path = StrDup(dir->diPath);
         f->name = StrDup(fd.cFileName);
         f->type = TYPE_DIRECTORY;
         count = AddToList(f,List,max,count);
      }
   }
   
   while(FindNextFile(h,&fd))
   {
      if(!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
      {
         //PrintF("adding new file1 - %i",count);
         f = Malloc(sizeof(MYFILE));
         f->path = StrDup(dir->diPath);
         f->name = StrDup(fd.cFileName);
         f->type = TYPE_FILE;
         count = AddToList(f,List,max,count);
         
      }
      else
      {
         if(StrCmp(fd.cFileName,".") != 0 && StrCmp(fd.cFileName,"..") != 0)
         {
            f = Malloc(sizeof(MYFILE));
            f->path = StrDup(dir->diPath);
            f->name = StrDup(fd.cFileName);
            f->type = TYPE_DIRECTORY;
            count = AddToList(f,List,max,count);
         }
      }
   }
   
   FindClose(h);
   
   //PrintF("finish searching");
   return count;
}

int SearchDirR(MHS_SEARCHDIRPARMS *dir, MYFILE **List, int curpos, int max)
{
   
   int foundcount = 0;
   bool freepath = false;
   char *tpath;
   
   if(StopThread)
         return curpos;
   //append the \ to the end
   if(dir->diPath[StrLen(dir->diPath)-1] != '\\')
   {   
      tpath = dir->diPath;
      dir->diPath = Malloc(StrLen(dir->diPath) + 2);
      StrCpy(dir->diPath,tpath);
      StrCat(dir->diPath,"\\");
      freepath = true;
   }
   
   //get list of wanted files
   curpos = FileList(dir,List,curpos,max);
   
   MHS_SEARCHDIRPARMS tmp;
   tmp.diPath = dir->diPath;
   tmp.diFile = "*";
   tmp.isSubDirSearch = 3;
   
   
   MYFILE *files[32768]; //enough for 32768 files
   //get a list of every file in current folder
   int count = FileList(&tmp,files,0,32768);
   
   for(int i=0;i<count;i++)
   {
      if(files[i]->type == TYPE_DIRECTORY
            && StrCmp(files[i]->name,".") != 0
            && StrCmp(files[i]->name,"..") != 0)
      {
         //PrintF("SearchDirR-forloop %s%s",files[i]->path,files[i]->name);
         MHS_SEARCHDIRPARMS newdir;
         char *path = Malloc(StrLen(files[i]->path) + StrLen(files[i]->name) + 2);
         StrCpy(path,files[i]->path);
         StrCat(path,files[i]->name);
         newdir.diPath = path;
         newdir.diFile = StrDup(dir->diFile);
         newdir.isSubDirSearch = 3;
         curpos = SearchDirR(&newdir,List, curpos,max);
         Free(path);
         Free(newdir.diFile);
      }
   }
   
   //now free all resource
   for(int i=0;i<count;i++)
   {
      Free(files[i]->path);
      Free(files[i]->name);
      Free(files[i]);
   }

   if(freepath) {
      Free(dir->diPath);
      dir->diPath = tpath;
   }
   return curpos;
   
}

INT SearchDir( MHS_SEARCHDIRPARMS *SInfo)
{    

   MYFILE *files[32768]; //enough for 32768 files
   int count = SearchDirR(SInfo,files,0,32768);
   
   
   if(count == 0)
   {
      char *path = Malloc(StrLen(SInfo->diPath) + StrLen(SInfo->diFile) + 1);
      StrCpy(path,SInfo->diPath);
      StrCat(path,SInfo->diFile);
      PrintF("nothing found - %s", path);
      Free(path);
   }
   else
   {
      PrintF("total found - %i", count);
   }
   for(int i=0;i<count;i++)
   {
      switch(files[i]->type)
      {
         case TYPE_DIRECTORY:
         {    
            PrintF("%s%s - DIR", files[i]->path,files[i]->name);
         break;
         }
         
         case TYPE_FILE:
         {
            PrintF("%s%s - FILE", files[i]->path,files[i]->name);
         break;
         }
      }
   }
   //now free them all
   for(int i=0;i<count;i++)
   {
      Free(files[i]->path);
      Free(files[i]->name);
      Free(files[i]);
   }
   
}
 
// Does that structure look familiar?  Its members are the parameters we need
//  to get into SearchDir().
 
// Now create a function that accepts this structure as its only parameter.
// Having one parameter of 4 bytes in size makes this function compatible
//  with CreateThread() (though any function can be called by CreateThread(),
//  it may have garbage in its parameters if not used correctly).
// Note that this is really just a shortcut.  Normally we would create this
//  function with a DWORD parameter and cast it to a MHS_SEARCHDIRPARMS *
//  inside the function, but this shortcut works the same and is faster too.
INT SearchDir_SecondThread( MHS_SEARCHDIRPARMS * psdpParms ) {
    // Our only objective here is to call SearchDir() with the correct
    //  parameters, however we have one other task to do here.
 
    // psdpParms is a pointer that was created by Malloc(), and it was not
    //  freed with Free() because our main thread wants to make sure it is
    //  alive long enough for this thread to use it (main thread below).
    // As a result, the main thread leaves it up to us to call Free() on
    //  this pointer.
 
    // But first, get the actual result.
    INT iRet = SearchDir(psdpParms );
   
    // Getting the result is that easy!
    // We only needed a pointer to the MHS_SEARCHDIRPARMS object, and inside that
    //  object we had all the other parameters we needed for the call to SearchDir.
 
 
    // But now we have to free the psdpParms object, so do it.
    Free( psdpParms->diPath );  // Created with StrDup(), so Free() it.
    Free( psdpParms->diFile );  // Created with StrDup(), so Free() it.
    Free( psdpParms );
 
    // Pass back the value.
    // The main thread is not waiting for this thread to finish, so it can not
    //  actually get this value, but it is proper to return it anyway.

   ThreadIdle = true;
   PrintF("search thread completed");
    return iRet;
}
 
 
 
// Finally, this is called by the main thread to start the second thread with the
//  correct parameters.
// It has the same paremeter list as SearchDir()!
INT SearchDir_MainThread( const CHAR * pcPath, const CHAR * pcFile, INT iSubDirSearchDepth ) {
    // This function is quite simple.
    // First, make an object that can hold these parameters.
    MHS_SEARCHDIRPARMS * psdpParms = Malloc( sizeof( MHS_SEARCHDIRPARMS ) );
    if ( (LPVOID)psdpParms == NULL ) { return -1; }
 
    // If that worked, copy the strings to a place where they will not be
    //  removed from memory while the second thread is working.
    psdpParms->diPath = StrDup( pcPath );
    psdpParms->diFile = StrDup( pcFile );
    psdpParms->isSubDirSearch = iSubDirSearchDepth;
 
    // Call the second thread with the pointer to this structure as its parameter.
    HANDLE hThread = CreateThread( "SearchDir_SecondThread", (DWORD)psdpParms );
 
    // If it failed, delete the structure ourselves.
    if ( !hThread ) {
      PrintF("Thread failure");
        Free( psdpParms->diPath );  // Created with StrDup(), so Free() it.
        Free( psdpParms->diFile );  // Created with StrDup(), so Free() it.
        Free( psdpParms );
 
        // No need to call CloseHandle() on a NULL handle.
        return -1;
    }
 
    // Coming here means the second thread is in motion, so let it delete
    //  the structure on its own when it is done.
    // Our work here is done.
    // Close our handle on the thread and get out of here.
 
    CloseHandle( hThread ); // This does not stop the second thread.  It just
                            //  releases our resources.
 
    PrintF( "Main thread closing." );
    // 1 for success, -1 for error.
    return 1;
}
 
 
// Our version of the standard StrDup() function.
// This will be added to the API in the next release!
/*CHAR * StrDup( const CHAR * pcString ) {
    INT iLength = StrLen( pcString ) + 1;
    CHAR * pcThis = Malloc( iLength );
    if ( !pcThis ) { return NULL; }
    // Because we used Malloc() here, the returned pointer will
    //  need to be deleted with Free() when it is done being used.
    StrCpy( pcThis, pcString );
    return pcThis;
}*/

VOID On_HK_0( DWORD dwP1, DWORD dwP2 ) {
   
    if(ThreadIdle)
    {
      Clear();
      PrintF("Starting search");
      StopThread = false;
      ThreadIdle = false;
      SearchDir_MainThread( "C:\\", "*.mp3", 3 );
    }
    else
    {
      PrintF("Search is in progress");
    }
}

//search stopper
VOID On_HK_1( DWORD dwP1, DWORD dwP2 ) {
   
   if(!ThreadIdle)
    {
      PrintF("Stopping search thread");
      StopThread = true;
   }
   else
   {
      PrintF("search thread is idle");
   }
}

hunter
I Have A Question
 
Posts: 1
Joined: Fri Jan 12, 2007 8:45 pm

Postby g3nuin3 » Fri Jan 12, 2007 11:18 pm

nice one hunter :)
g3nuin3
Acker
 
Posts: 96
Joined: Tue Jul 18, 2006 10:53 am


Return to Help

Who is online

Users browsing this forum: No registered users and 0 guests

cron