42. SHFileOperation gives file system error 1026. Why?
This problem comes up periodically, and is usually due to
the lack of double-nulling which SHFileOperation requires in its parameters
(because they can be multi-file lists, delimited with single NULLs and
terminated with a double NULL). Take the following code (this is all done in debug mode, by the way) :
void CTestbed2Dlg::test_shfo (CString& csFilesSrc, CString& csFilesDst)
{
SHFILEOPSTRUCT shfos;
char szDebug [100];
int iSHerr;
shfos.hwnd = GetSafeHwnd();
shfos.wFunc = FO_COPY;
shfos.pFrom = csFilesSrc;
shfos.pTo = csFilesDst;
shfos.fFlags= FOF_NOCONFIRMATION;
shfos.lpszProgressTitle = "Testbed2";
iSHerr = SHFileOperation (&shfos);
if (iSHerr == 0)
AfxMessageBox ("Worked fine");
else
{
wsprintf (szDebug, "SHFO gave error %d", GetLastError());
AfxMessageBox (szDebug);
}
}
and call it like this :
CString csSrc;
CString csDst;
csSrc = "C:\\Scratch\\*.*";
csDst = "d:\\Scratch";
test_shfo (csSrc, csDst);
You'll get file system error 1026 every time. Modify the
function code to use local arrays like this :
void CTestbed2Dlg::test_shfo (CString& csFilesSrc, CString& csFilesDst)
{
SHFILEOPSTRUCT shfos;
char szDebug [100];
int iSHerr;
char szSrc [_MAX_PATH];
char szDst [_MAX_PATH];
strcpy (szSrc, csFilesSrc);
strcpy (szDst, csFilesDst);
shfos.hwnd = GetSafeHwnd();
shfos.wFunc = FO_COPY;
shfos.pFrom = szSrc;
shfos.pTo = szDst;
shfos.fFlags= FOF_NOCONFIRMATION;
shfos.lpszProgressTitle = "Testbed2";
iSHerr = SHFileOperation (&shfos);
if (iSHerr == 0)
AfxMessageBox ("Worked fine");
else
{
wsprintf (szDebug, "SHFO gave error %d", GetLastError());
AfxMessageBox (szDebug);
}
}
and call it exactly the same way, (note - still no
explicit double-nulling), and it will work. More interestingly, if you leave the
function code in its first form and call it like this.....
CString csSrc ('\0', _MAX_PATH);
CString csDst ('\0', _MAX_PATH);
csSrc = "C:\\Scratch\\*.*";
csDst = "d:\\Scratch";
test_shfo (csSrc, csDst);
...now
the code will magically work. That odd CString constructor pre-fills
the string, by the way. It looks like the problem lies with the lack of double nulling. So, to prove it, do this to the code which invokes
SHFO
char szSrc [_MAX_PATH];
char szDst [_MAX_PATH];
// pack the arrays
memset (szSrc, 'A', sizeof(szSrc));
memset (szDst, 'A', sizeof(szDst));
// now copy in the strings (no double nulls)
strcpy (szSrc, csFilesSrc);
strcpy (szDst, csFilesDst);
shfos.hwnd = GetSafeHwnd();
shfos.wFunc = FO_COPY;
shfos.pFrom = szSrc;
shfos.pTo = szDst;
and the 1026 error comes back again.
Update, courtesy of Phil Wright:
This error value (1026) is also produced if an FO_DELETE operation is attempted for a file that doesn't
exist, even if the string ends in a double-null.
I have confirmed this. See this code:
SHFILEOPSTRUCT shfos = {0};
int iSHerr;
char szSrc [MAX_PATH];
ZeroMemory (szSrc, sizeof(szSrc));
strcpy (szSrc, "C:\\squiggly.zap");
shfos.hwnd = NULL;
shfos.wFunc = FO_DELETE;
shfos.pFrom = szSrc;
shfos.fFlags = FOF_NOERRORUI | FOF_NOCONFIRMATION | FOF_SILENT;
iSHerr = SHFileOperation (&shfos);
if (iSHerr == 0)
{
AfxMessageBox ("squiggly.zap deleted ?! It doesn't exist
!");
}
else
{
wsprintf (g_szDebug, "MF: SHFileOperation gave error %d",
iSHerr);
AfxMessageBox (g_szDebug);
}
That code will also produce error 1026, despite being correct apart from one
vital fact - C:\squiggly.zap doesn't exist
(on my system anyway :-)). It seems that 1026 really means
"something went wrong" :-(