Welcome to shell: revealed Sign in | Join | Help
in Search

Shell Blog

Common Questions Concerning the SHFileOperation API: Part 1

Over the years, I have seen many questions being asked on newsgroups and developer forums concerning the SHFileOperation API.  This API allows developers to perform file operations such as Copy, Move, Rename and Delete as well as provide rich UI for confirmation, error and progress dialogs. 

The API uses a struct named SHFILEOPSTRUCT, which contains many members and possible flags/values for those members.  As a consequence, there are many dark corners of the API that need better clarification.  While the documentation on MSDN contains helpful nuggets of information, I wanted to address some of the more commonly asked questions in this multi-part blog entry. 

Part 1:  Why does SHFileOperation return incorrect error codes that have nothing to do with what actually went wrong?

The newsgroups are filled with developers asking questions such as: "SHFileOperation returned error code 117 which maps to ERROR_INVALID_CATEGORY.   This doesn't make any sense!"

In the context of Win32 - that developer is correct.  The description for ERROR_INVALID_CATEGORY in winerror.h is: "The IOCTL call made by the application program is not correct."  What in the world does SHFileOperation have to do with IOCTL errors???   Absolutely nothing.  SHFileOperation isn't returning ERROR_INVALID_CATEGORY.  In this example it is actually returning DE_OPCANCELLED (0x75).  Don't bother searching for what DE_OPCANCELLED is.  It's not documented. 

Many of the error codes returned from SHFileOperation are either old DOS codes from the pre- Win32 era, or custom error codes defined in the copy engine for the old File Manager.  The SHFileOperation API was created from this code and first appeared in Windows 95/NT 4.  At the time, changing the error codes was not foreseen as a priority.  The problem that we see today is that these error codes overlap with those defined in winerror.h.  Other Shell APIs behave the same way.  For example, the ShellExecute API documentation states that any return code lower than 32 is an error.  Above that, it succeeded.  These are old DOS error codes as well.

For reference, below is a table of the error codes returned from SHFileOperation along with their corresponding description.

Error Code





Source and destination file are the same



Multiple paths were specified in the source of the operation, but only one destination path



Rename operation was specified but the destination path is a different directory.  Use move instead.



Source is a root directory, cannot be moved or renamed



Operation was cancelled by the user (or silently cancelled if the specified flags were supplied to SHFileOperation)



The destination is a sub-tree of the source



Security problems on source



The source or destination path exceeded or would exceed MAX_PATH



Operation involved multiple destination paths which can fail in the case of a move operation



The paths in the source or destination were invalid



Source and destination have the same parent folder.



The destination path is to an existing file



The destination path is to an existing folder



The name of the file exceeds MAX_PATH



Destination is a Read-Only CDRom, possibly unformatted



Destination is a Read-Only DVD, possibly unformatted



Destination is a Recordable (AudioL) CDRom, possibly unformatted



The file involved in the operation is too large for the destination media or file system



Source is a Read-Only CDRom, possibly unformatted



Source is a Read-Only DVD, possibly unformatted



Source is a Recordable (AudioL) CDRom, possibly unformatted



MAX_PATH was exceeded during the operation.

Generic Error


An unknown error occurred. This is typically due to invalid paths in the source or destination. This error does not occur on Vista and greater.



An unspecified error occurred on the destination.



Destination is a root directory, cannot be renamed

Correcting this error code overlap at this point is simply not practical.  Too many applications are written to expect these specific error codes.  Changing SHFileOperation to return valid winerror.h defined error codes could break these applications.    Please note that the above error codes are subject to change (as they have in previous versions of Windows) and I want to stress that there is NO OFFICIAL SUPPORT FOR THESE ERROR CODES.  As MSDN calls out:  Your code should only check if SHFileOperation returned zero or non-zero.  I only call them out here to add some clarity for those developers debugging their code.  If you want to know for sure why an operation failed you will have to roll your own operations engine.

The silver lining to this story is that in Vista a new interface has been written to allow developers to move away from SHFileOperation's confusing error codes to correctly mapped HRESULT values.  That interface is IFileOperation and will be the topic of later posts.

Published Monday, September 11, 2006 2:53 AM by chrdavis



erangi said:

What a glorious post! This is actually the only documentation of those return values on the Web. What a rare situation for such a commonly used function.

Now, I've happily added all those codes to my application, hoping that it would give me some clue about what's failing the function. When I reproduced the problem, the return code was 32, which is not one of the error codes described... 32 was also the LastError code (as reported by @err, GetLastError wasn't used...), and it actually did make some sense - I was trying to move a folder that contained an open file. From your post I understand it is possible that an internal function SHFileOperation calls will set the last error variable, but why would SHFO itself return that code?

October 3, 2006 8:58 AM

chrdavis said:

You should not be relying on GetLastError to return you anything meaningful about the error that occurred.  It is only luck that the last error and the error returned from SHFileOperation were the same error code.

There seems to be some misunderstanding about this post.  SHFileOperation will return valid error codes that map to the correct values in winerror.h for most cases.  It is only in a few cases that I called out in this post where the values overlap those in winerror.h and can lead to some confusion.  

erangi - in your case you get back error code 32 - which maps to ERRROR_NOT_SUPPORTED or ERROR_SHARING_VIOLATION (more likely the latter) from winerror.h.  Use the error lookup tool in Visual Studio or call FormatMessage with the error code returned to get the description.  If the error code matches one of the values I called out, you will have to special case your error handling if you want to give a meaningful error message to the user.

Please see my second post on SHFileOperation in this blog which outlines the most common errors in using the API.  

October 3, 2006 2:17 PM

erangi said:

Reading the list of error messages, something looks a bit strange...

There are two error messages that refer to the use of DVD. According to Wiki, the first DVD players were introduced (in Japan) on 1996, and it took them several more years to get to the first personal computers. So, is this some late addition, or is it a smart prediction? if the former, why would anyone add a DE message after winerror was introduced? if the later, it's a pitty those prediction abilities hadn't been used to predict winerror.h as well... ;-)

November 1, 2006 5:06 AM
Anonymous comments are disabled
Powered by Community Server, by Telligent Systems © 2006 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement.