Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using SHFileOperation: What errors are occuring

Tags:

c++

winapi

I am using the function SHFileOperation() to send a file to the recycling bin and I am getting 2 errors that I do not know what they mean because with this function the error codes are not GetLastError() values.

When the function SHFileOperation() fails the return values are 0x57 (decimal 87) and 0x2 (decimal 2). Can anyone help me discover the definitions of these errors (expecially when you consider with this function, the errors are not part of the GetLastError() codes).

Some important information:

  • I am using Windows 7 (& I know that MSDN says to use IFileOperation instead of SHFileOperation but I want to make my app backwards compatable which is why I am using SHFileOperation). If the error is occuring because I am using SHFileOperation on Windows 7 what solution could I use to make this work on all versions of windows from 2000 & up?

  • I have debugged extensively & as far as I know my SHFILEOPSTRUCT is correct (correct flags used, .pFrom is a double-null ended string). One thing I know for sure is that my path to the file is correct (leads to a real file & it correctly formatted).

  • About 2/5 times the SHFileOperation() works, meaning it sends the file to the recycle bin & does not returns an error

.

 BOOL result;
 SHFILEOPSTRUCT fileStruct;
 fileStruct.hwnd = hwnd; 
 fileStruct.wFunc = FO_DELETE;
 fileStruct.pFrom = dest.c_str();
 fileStruct.fFlags = FOF_FILESONLY; // FOF_ALLOWUNDO
 fileStruct.fAnyOperationsAborted = result;

 // Call operation(delete file)
 int success = SHFileOperation( &fileStruct );

 // if delete was successful
 if ( success != 0 ) 
 {
    printf( "%s \t %X %d \n", dest.c_str(), success, success );
    cout << result << endl;

    MessageBox( hwnd, "Failed to delete file", "Error", MB_OK|MB_ICONERROR );
    return;
 }
like image 257
Sascha Avatar asked Dec 31 '10 04:12

Sascha


4 Answers

As shf301 said, error code 87 is ERROR_INVALID_PARAMETER. This probably occurs because you're not initialising the contents of the unused SHFILEOPSTRUCT fields, so they will contain random values. The documentation says that pTo "must be set to NULL if it is not used"; the OS might be checking the value of this field and returning an error if it's non-NULL.

First set everything to zero by either doing:

SHFILEOPSTRUCT fileStruct = { 0 };

or

SHFILEOPSTRUCT fileStruct;
ZeroMemory(&fileStruct, sizeof(SHFILEOPSTRUCT));

Error code 2 is ERROR_FILE_NOT_FOUND; it's probably safe to ignore this error code if it's possible that the file doesn't exist, or that the user has deleted it before your program tries to delete it. (Note that even if you check that the file exists before you try to delete it, another process could have deleted it in the meantime, so you will always need to handle this error.)

like image 174
Bradley Grainger Avatar answered Nov 18 '22 02:11

Bradley Grainger


Some serious problems with this snippit, i'd suggest reading SHFILEOPSTRUCT structure

  1. pFrom must be doubly null terminated. I don't know what type dest is but it almost certainly isn't returning a doubly null terminated string.

  2. pTo parameter must be set to NULL if it is not used. Wildcard characters are not allowed. Their use will lead to unpredictable results.

  3. safe practice would be to call zero memory on the struct before you fill it

    SHFILEOPSTRUCT shStruct;
    ZeroMemory (&shStruct, sizeof(SHFILEOPSTRUCT));

  4. fileStruct.fAnyOperationsAborted = result; won't put the value the function returns into result. the SHFILEOPSTRUCT exists on the stack and can simply be read from after the call

These issues by themselves explain the error codes your getting.

like image 30
8bitwide Avatar answered Nov 18 '22 00:11

8bitwide


According to the SHFileOperation documentation, those errors map to the standard Windows error codes from WinError.h you can lookup those error codes at this page on MSDN.

Your errors would appear to be:

ERROR_FILE_NOT_FOUND 2 (0x2) The system cannot find the file specified.

and

ERROR_INVALID_PARAMETER 87 (0x57) The parameter is incorrect.

like image 2
shf301 Avatar answered Nov 18 '22 01:11

shf301


When working with wide strings with SHFileOperation, not only do you need to double-null terminate the string, but because pFrom is a list of strings, you must double-double-null terminate your path string :

So , In fileStruct.pFrom = dest.c_str(); statement there's no guarantee that will give you a double null.

You must do this before assignment :

WCHAR wszFrom[MAX_PATH] = { 0 };
StrCpyW(wszFrom, dest.c_str());
CopyMemory(wszFrom + lstrlenW(wszFrom), "\0\0", 2);

Then assign the double-double-null string :

fileStruct.pFrom = wszFrom;

You can prevent of this error :

ERROR_FILE_NOT_FOUND 2 (0x2) The system cannot find the file specified.