CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Sep 2004
    Posts
    118

    Recursion in DLL

    **EDIT**
    the code is actual not working properly at all. it crashes quickly after only searching a few files out. it only started generating error reports when i added a few messageboxes to the code to see each file and folder found...
    **EDIT**

    I am writing a function in a DLL that scans through all files on a drive and decompresses any NTFS files that are compressed.

    The filecount variable is defined in the .h and keeps track of how many files have been found on the drive.

    The variable char **megabuffer is defined in the .h file and stores the full path names of each file on the hard drive.

    The variable int *uarray is defined in my .h file and keeps track of which files in megabuffer were decompressed successfully. For example, uarray[0] might store the number 4, meaning megabuffer[4] contains a file path of a file that was decompressed successfully.

    I am planning on writing another function that returns the file path of each of the files that was decompressed successfully.

    I have not worked with recursive functions much before, and I am particular uncertain about how the stack will work with the recusion, and if my DLLs code has problems related to this.

    If an application calls the dcmp32 function twice, will there be conflict with the uarray and megabuffer variables being accessed twice? Or will a new set of variables be used for each call to the function?

    I plan on using a separate function to free() the dynamically allocated memory.

    Any advice about problems with the code would be really helpful as I'm not entirely confident about what I have so far, although it appears to be working properly. Not used to working with recusion and DLLs.

    Here is the code. Thanks for any tips.

    Code:
    #include "dll.h"
    #include <windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    #define ID_LIST 1
    #define FILE_DEVICE_FILE_SYSTEM 0x00000009
    #define METHOD_BUFFERED 0
    #define CTL_CODE2(de,fc,meth,acs)(\
    ((de)<<16)|((acs)<<14)|((fc)<<2)|(meth)\
    )
    #define FSCTL_SET_COMPRESSION2 CTL_CODE2(FILE_DEVICE_FILE_SYSTEM,16,METHOD_BUFFERED,FILE_READ_DATA|FILE_WRITE_DATA)
    __declspec (dllexport) int dcmp32(const char *drive)
    {
        int drivelen=strlen(drive);
        if(drivelen>512)
        {
            goto cleanup;
        }
        char *wc=(char *)malloc(drivelen+2);
        memset(wc,0x0,drivelen+2);
        strncpy(wc,drive,drivelen);
        strncat(wc,"*",1);
    	HANDLE search=0;
    	WIN32_FIND_DATA wfd;
        BOOL rcode=TRUE;
        search=FindFirstFile(wc,&wfd);
        if(search==INVALID_HANDLE_VALUE)
        {
            free(wc);
            goto cleanup;
        }
        free(wc);
        unsigned len2=0;
        unsigned tot=0;
    	for(;rcode;rcode=FindNextFile(search,&wfd))
    	{
            len2=0;
            tot=0;
    		if(wfd.cFileName[0]=='.')
    		{
    			continue;
    		}
            ++filecount;
            megabuffer=(char **)realloc(megabuffer,filecount*(sizeof(char *)));
    		if(wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
    		{
                len2=strlen(wfd.cFileName);
                tot=drivelen+len2+1+1;
                megabuffer[filecount]=(char *)malloc(tot);
                memset(megabuffer[filecount],0x0,tot);
                strncpy(megabuffer[filecount],drive,drivelen);
                strncat(megabuffer[filecount],wfd.cFileName,len2);
                strncat(megabuffer[filecount],"\\",1);
                MessageBox(0,megabuffer[filecount],"good",0);
                DWORD attrib=GetFileAttributes(megabuffer[filecount]);
                if(attrib&FILE_ATTRIBUTE_COMPRESSED)
                {
    
                    HANDLE h=CreateFile(megabuffer[filecount],GENERIC_ALL,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
                    if(h==INVALID_HANDLE_VALUE)
                    {
                    }
                    USHORT comp=COMPRESSION_FORMAT_NONE;
                    DWORD lpB;
                    if(DeviceIoControl(h,FSCTL_SET_COMPRESSION2,&comp,sizeof(comp),0,0,&lpB,0)==0)
                    {
                    }
                    else
                    {
                        ++dfiles;
                        uarray=(unsigned *)realloc(uarray,dfiles*sizeof(unsigned));
                        uarray[dfiles]=filecount;
                    }
                    CloseHandle(h);
    
                }
                dcmp32(megabuffer[filecount]);
            }
            else
            {
                len2=strlen(wfd.cFileName);
                tot=drivelen+len2+1;
                megabuffer[filecount]=(char *)malloc(tot);
                memset(megabuffer[filecount],0x0,tot);
                strncpy(megabuffer[filecount],drive,drivelen);
                strncat(megabuffer[filecount],wfd.cFileName,len2);
                MessageBox(0,megabuffer[filecount],"good",0);
                DWORD attrib=GetFileAttributes(megabuffer[filecount]);
                if(attrib&FILE_ATTRIBUTE_COMPRESSED)
                {
    
                    HANDLE h=CreateFile(megabuffer[filecount],GENERIC_ALL,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
                    if(h==INVALID_HANDLE_VALUE)
                    {
    
                    }
                    USHORT comp=COMPRESSION_FORMAT_NONE;
                    DWORD lpB;
                    if(DeviceIoControl(h,FSCTL_SET_COMPRESSION2,&comp,sizeof(comp),0,0,&lpB,0)==0)
                    {
    
    
                    }
                    else
                    {
                        ++dfiles;
                        uarray=(unsigned *)realloc(uarray,dfiles*sizeof(unsigned));
                        uarray[dfiles]=filecount;
    
                    }
                    CloseHandle(h);
                }
            }
        }
        FindClose(search);
        cleanup:
        return 0;
    }
    BOOL APIENTRY DllMain(HINSTANCE hInst,DWORD reason,LPVOID reserved)
    {
        switch(reason)
        {
            case DLL_PROCESS_ATTACH:
                break;
            case DLL_PROCESS_DETACH:
                break;
            case DLL_THREAD_ATTACH:
                break;
            case DLL_THREAD_DETACH:
                break;
        }
        return TRUE;
    }
    Last edited by c0ldshadow; December 10th, 2006 at 10:57 AM.

  2. #2
    Join Date
    Aug 2005
    Posts
    478

    Re: Recursion in DLL

    You don't have to worry about the globals, each process gets it's own set of them (shared memory would allow multiuple processes to use the same ones). And, nothing is wrong with ordinary recursion, but the fact is the your app needs to go through the whole directory tree, which could be extraordinarily deep, and potentially cause a stack voerflow in your code. This is a case that is definitely worth checking for.
    Windows XP, Visual Studio 2008, SVN

  3. #3
    Join Date
    Nov 2006
    Posts
    1,611

    Re: Recursion in DLL

    ...and frankly I wouldn't worry too much about recursive depth on a directory tree driven algorithm.

    There was a time, yes, when this little bit of recursive depth would be a concern, and still there are certain target environments where you'll have the caveat, but I assume this is Windows from the modern era (no Windows 98, all from NT 4.0 forward through Vista).

    Even though hard drive depths can reach, say, 100 levels deep, this is hardly a problem with recursive algorithms, with a few caveats.

    I've never encountered a stack overflow unless I deliberately (or stupidly) created a non-terminated recursive call, or failed to consider the RAM requirements of deep recursions.

    If you create buffers on the stack, or other larger values (say, you created a 1Kbyte buffer on the stack at each recursion) - and assuming you're running the application on a 32bit Windows machine with, say, 512Mbytes RAM, you MIGHT have a RAM allocation problem if the recursion exceeds, say, 10,000 levels of depth.

    That is, you can instruct the LINKER to reserve large amounts of RAM for the stack if you think you need it.

    As an example, the default settings on VS2005 allowed me to create a simple recursive call, and place a 128 byte buffer in each call whereby, in the debugging run, the application crashed after a few thousand recursions.

    Raising the linker's option for the stack allocation size allowed me to reach 100,000 recursive calls.

    Even within the debugger, the recursion into 100,000 calls, and to unwind them, happened in the snap of a finger on a 2Ghz AMD CPU.

    This does NOT mean you can simply ignore recursive depth. However, the likely depth of a directory search is going to be within a range that fits easily into the maximums of the operating system.

    You may also consider exception handling to gracefully back out of a problem if it occurs (in which case the user has one incredible volume of directories).

  4. #4
    Join Date
    Sep 2004
    Posts
    118

    Re: Recursion in DLL

    thanks for the responses.

    calculator, i was wondering what would happen though if tbe same process calls the dcmp32 function twice. could this cause problems?

  5. #5
    Join Date
    Aug 2005
    Posts
    478

    Re: Recursion in DLL

    Well, it has thread safety issues, but I don't know if that's what you were talking about. Just make sure you clean up resources and stuff and the same process should be able to call it a billion times if it really feels like it.
    Windows XP, Visual Studio 2008, SVN

  6. #6
    Join Date
    Sep 2004
    Posts
    118

    Re: Recursion in DLL

    My code is actually not working properly at all; I don't know what the problem is. I've been looking at what I have for hours but have been unable to stop the crash. When I call the function from the DLL, after only a few MessageBoxes pop up, the program crashes. It always crashes after finding the same file.

    Is it possible that somehow the messageboxes alone are causing the crash? the program only crashes when messageboxes are added.. but either way it is not working properly. its not coming close to enumerating thru all the files either way.

    One thing I tried was doing:

    Code:
    dcmp32(strdup(megabuffer[filecount]));
    Instead of:

    Code:
    dcmp32(megabuffer[filecount]);
    That didn't make any difference though.

    Here is the code I'm using to call the DLLs function:

    Code:
    #include <windows.h>
    int main(int argc,char **argv)
    {
        typedef int (__stdcall *pfunc)(const char *);
        HMODULE h=LoadLibrary("G:\\c0ldshadow\\dev\\dcmp32\\dcmp32.dll");
        if(h==0)
        {
            MessageBox(0,"asd","asd",0);
            return 1;
        }
        pfunc myFunc=(pfunc)GetProcAddress(h,"dcmp32");
        if(myFunc==0)
        {
            MessageBox(0,"bad","bad",0);
            return 1;
        }
        if(myFunc("c:\\")==0)
        {
    
        }
    
        FreeLibrary(h);
        return 0;
    }
    Thanks for any help.
    Regards,
    -c0ldshadow
    Last edited by c0ldshadow; December 10th, 2006 at 11:10 AM.

  7. #7
    Join Date
    Aug 2005
    Posts
    478

    Re: Recursion in DLL

    I don't get it. Why would you be doing those things? A bufer isn't passed as the parameter. It's returned. But not really, because in your code you always return 0, I don't see how you get the megabuffer.
    Windows XP, Visual Studio 2008, SVN

  8. #8
    Join Date
    Sep 2004
    Posts
    118

    Re: Recursion in DLL

    Calculator, I was going to implement another function to return the contents of megabuffer.


    I think I found part of the problem... the program crashes when realloc returns NULL.

    something is wrong with my realloc

    i put:

    Code:
            megabuffer=realloc(megabuffer,filecount*8);
    this appears to fix the problem.

    what should i have though, for parameter 2 of realloc?
    Last edited by c0ldshadow; December 11th, 2006 at 11:23 AM.

  9. #9
    Join Date
    Nov 2006
    Posts
    1,611

    Re: Recursion in DLL

    You're experience the classic symptoms of C level allocation issues.

    Sorry, I've not run through to find your specific problem - I'd probably have to run it in a debugger to see it, but the general issue is the megabuffer as a concept.

    You have an unpredictable volume coming from a disk drive, and an array is not well suited for this.

    You really should consider a linked list, perhaps even a tree - maybe one of the STL containers would do.

    Since I don't think you'll have much rearrangement of the resulting data, perhaps you can build the list on the fly, simply by making a class or struct to hold the strings you're using in megabuffer (and any other data you're holding per file), and allow a pointer in that structure to show where the next one is (standard single linked list).

    Containment issues are a classic bug, and the reason Java fans point to C++ and C as problematic. In C++, disciplined developers use objects to eliminate the problem, and those kinds of bugs.

    Objects like the STL containers.

  10. #10
    Join Date
    Dec 2006
    Posts
    1

    Re: Error in DLLMain

    I'm trying for the main function.

    BOOL WINAPI DllMain (HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved)

    When I use this main function its giving me error like

    Error C2731: 'Dll Main' " function cannot be overloaded
    Error C2733: Second C linkage of overloaded function 'DllMain' not allowed

    Thanks in advance

    Hameed

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured