Search code examples
windowsc++-cli

C++ - Copying an image to System32


I'm writing a program changing your lock screen background on Windows 7, in C++/CLI. (I know it's a bad idea, but I can't do otherwise at this moment.) It takes an image called backgroundDefault.jpg and copies it to C:\Windows\System32\oobe\info\backgrounds, after modifying the corresponding registry key and creating the necessary folders.

The problem is that when I launch this code it doesn't get copied: oobe\info\backgrounds is empty. I've one it in batch first and it worked perfectly. In C++ it's another story. I've tried five different ways and they do not work.

system("xcopy xcopy backgroundDefault.jpg %windir%\\System32\\oobe\\info\\backgrounds\\ /Y >nul");

Checked the log on the command prompt in debugging: I get the confirmation that it worked but nothing happened.

I tried putting this command in a batch-file and ran it. I get the confirmation, but nothing actually happened.

system("theme_ls_copy.bat");

(I'm also trying to stay away from the system() command as much as possible.)

I've also tried using CopyFile(), and it didn't work as well.

CopyFile(L"backgroundDefault.jpg", L"C:\\Windows\\System32\\oobe\\info\\backgrounds\\backgroundDefault.jpg", 0);

I tried ShellExectue() too, without any success since it gave me a LNK error.

ShellExecuteA(GetDesktopWindow(),L"open", L"theme_ls_copy.bat", NULL, NULL, SW_SHOW);

Even CreateProcess() doesn't help.

STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
if (CreateProcess(L"theme_ls_copy.bat", NULL, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo)) {
    WaitForSingleObject(processInfo.hProcess, INFINITE);
    CloseHandle(processInfo.hProcess);
    CloseHandle(processInfo.hThread);
}

What should I try?


Solution

  • Your program does not have the required privileges to write to the System32 directory - this is by design - imagine what would happen if any program could just access and replace files in protected system directories....

    That said, there's several ways you can try to do this, you first need acquire administrative rights, for instance via an embedded application manifest, or using ShellExecute with the runas argument - example here.

    Running with administrative rights does not automatically grant you access to everything - it does however allow you to request certain privileges to be set. You could try using AdjustTokenPrivileges function to acquire the SE_RESTORE_NAME (SeRestorePrivilege) privilege which grants

    [Microsoft]... write access control to any file, regardless of the ACL specified for the file

    Acquiring the SE_RESTORE_NAME privilege will likely involve the following workflow - granting (or starting) your process as an member of the Administrator group, looking up the luid of the privilege with LookupPrivilegeValue and then using the luid obtained to enable (SE_PRIVILEGE_ENABLED) on the process which requires write access to the directory - example here.

    Your mileage may vary but this should help you get there ;)