Skip to content

Instantly share code, notes, and snippets.

@mqudsi
Created October 16, 2011 05:25
Show Gist options
  • Save mqudsi/1290539 to your computer and use it in GitHub Desktop.
Save mqudsi/1290539 to your computer and use it in GitHub Desktop.
SHFileOperation for recursive folder copy
bool SHCopy(LPCTSTR from, LPCTSTR to)
{
Log(_T("Recursive file copy from %s to %s"), from, to);
SHFILEOPSTRUCT fileOp = {0};
fileOp.wFunc = FO_COPY;
TCHAR newFrom[MAX_PATH];
_tcscpy_s(newFrom, from);
newFrom[_tcsclen(from) + 1] = NULL;
fileOp.pFrom = newFrom;
TCHAR newTo[MAX_PATH];
_tcscpy_s(newTo, to);
newTo[_tcsclen(to) + 1] = NULL;
fileOp.pTo = newTo;
fileOp.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR;
int result = SHFileOperation(&fileOp);
Log(_T("SHFileOperation return code: 0x%x"), result);
return result == 0;
}
//sample call, E:\ is a USB stick
bool result = SHCopy(_T("E:\\*"), _T("C:\\SomeDirectory\\"));
//when called on XP SP3 and with the flag FOF_SILENT, this fails with 0x4C7 (ERROR_CANCELLED)
//removal of FOF_SILENT makes it work >.<
@myd7349
Copy link

myd7349 commented Jul 11, 2024

Worked! Nothing else worked because of double null terminators issues. Don't know why MS used double nulls, but seems like a hack.

https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-shfileopstructa

Although this member is declared as a single null-terminated string, it is actually a buffer that can hold multiple null-delimited file names. Each file name is terminated by a single NULL character. The last file name is terminated with a double NULL character ("\0\0") to indicate the end of the buffer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment