SHFileOperation copying folders using strings

2019-05-14 13:22发布

问题:

I am trying to copy a folder by SHFileOperationA function. Here is my code.

int main()  {

    SHFILEOPSTRUCTA sf;
    int result;

    string source = "D:\\check\\folder4";
    string dest = "D:\\Documents\\test\\folder4";

    sf.pFrom = source.c_str( );
    sf.pTo = dest.c_str( );
    sf.wFunc = FO_COPY;
    sf.fFlags = FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_SILENT;

    result = SHFileOperationA(&sf);

    return 0;
}

I am not able to understand that how to make the string appended by \0 twice. I tried something like this.

    string source = "D:\\check\\folder4\\0\\0";
    string dest = "D:\\Documents\\test\\folder4\\0\\0";

But, it is not working. I have also tried few more combinations but none of them is working. Please can anyone suggest me how to solve this?

I can solve the problem by directly assigning the paths like this:-

    sf.pFrom = "D:\\check\\folder4";
    sf.pTo = "D:\\Documents\\test\\folder4";

and the problem gets solved but my intention is to make use of strings. Please can anybody help me with this.

Also, if possible can anybody tell me why directly assigning the string constant i.e sf.pFrom = "D:\\check\\folder4"; is working and assigning using a string like sf.pFrom = source.c_str( ); is not working?

Thanks in advance.

回答1:

The std::string does strlen (or similar) to find the end of the constant char array and allocates only the required number of characters. So it stops on the first null and does not copy the other one. If you want to override this, you need to use constructor that takes size, like:

string source("D:\\check\\folder4\\0", 18);

Note that the second null character is added automatically just as with any other string.

Or add the null character explicitly like (way better solution):

std::string source = std::string("D:\\check\\folder4") + std::string(1, '\0');

Or

std::string source = "D:\\check\\folder4";
source.append(1, '\0');

As for the other question, why using constant character array works:

I believe that, if it works, it just a pure luck that the byte/character in memory after the constant character array is null.

You can test this yourself (in debugger or by printing the values):

// this is the compiler generated null
(*(sf.pFrom + strlen(sf.pFrom))) == '\0'

// this is the following byte/character that should be luckily null
(*(sf.pFrom + strlen(sf.pFrom) + 1)) == '\0' 

If you find that the following character is not null in debugger, make sure you finish debugging until the SHFileOperationA. As in that particular case it can fail/crash/whatever (while it normally does not) as the fact you are debugging alone may make the memory image different.

Also you have not specified what you exactly mean by "it works". Do you mean result of SHFileOperationA (what is it). Or that the application crashes/throws, when it does not work. Or that the files are copied or not. This might help answering you.