0

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?

PointR
  • 81
  • 13
  • The `System32` directory is a protected directory, do you have the elevated privileges needed to write to it? And the full path exists already? – Some programmer dude Jun 16 '17 at 06:31
  • As I wrote down, the folders are created before copying the image file. I also have the correct permissions. – PointR Jun 16 '17 at 06:34
  • GetLastError(). – zdf Jun 16 '17 at 06:46
  • @ZDF I'm sure I'm using this function wrong... How am I supposed to use it? Should I get an error message popup? – PointR Jun 16 '17 at 07:00
  • No error message. Just an error code. Look for it on MSDN. If you are using VisualC, there is an error lookup command under Tools menu. – zdf Jun 16 '17 at 07:06
  • I can't find the error code and I can't display it. Mind that I'm working in CLI (Should've wrote this on my initial post... Derp.) and that there isn't any console in the background. – PointR Jun 16 '17 at 07:15
  • `I can't display it` You could write it to a file (one not in System32) – deviantfan Jun 16 '17 at 07:17
  • Found a way to get this error as a string and wrote it on a file, but it says there actually are no errors. – PointR Jun 16 '17 at 07:28
  • It must be called after each system function. Otherwise, it might be reset. Call it immediately after CopyFile. – zdf Jun 16 '17 at 07:37
  • Realised the function was at the wrong place. Anyway I'm still getting nothing. :/ – PointR Jun 16 '17 at 07:51
  • Check your antivirus. – zdf Jun 16 '17 at 08:33
  • There are no antiviruses. I'm using a clean and empty Windows 7 VM. – PointR Jun 16 '17 at 08:34
  • I wonder if VM has anything to do with this. – zdf Jun 16 '17 at 08:59
  • 2
    Best guess: your application is 32-bit, so whenever you try to access `system32` you are actually getting `syswow64`. Build as 64-bit, or use `sysnative` in place of `system32`. – Harry Johnston Jun 17 '17 at 00:30
  • I'll try that once I'm back in the office, thanks. Though I'm not quite sure that'd be the case since nothing is getting copied to SysWow64. – PointR Jun 17 '17 at 07:52
  • @HarryJohnston I just build my project in 64-bit, and it worked like a charm. Thanks a lot! – PointR Jun 19 '17 at 07:10
  • PointR, you're welcome, and welcome to Stack Overflow! I've closed this question as a duplicate, since there was an existing question asking about the same problem. Please note that this does *not* mean there was anything wrong with your question, or that you should delete it; having duplicates like this one helps other people find the right answer. – Harry Johnston Jun 19 '17 at 21:34

1 Answers1

1

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 ;)

Ðаn
  • 10,934
  • 11
  • 59
  • 95
Anthill
  • 1,219
  • 10
  • 20
  • Tried both ways. The first one doesn't work, and the second one gives me three errors: LNK2028, LNK2019, and LNK1120. Note that I already have UAC prilieges on this program. – PointR Jun 16 '17 at 07:57
  • @PointR You mention that you have UAC privileges on the program - how are these privileges acquired? Moreover you say the second way (which is what?) gives you 3 errors: LNK2028, LNK2019, and LNK1120. These are linking errors - not run-time errors. your program is not compiling. Better post some code... – Anthill Jun 16 '17 at 08:02
  • The first way is with the embedded application manifest. I've got UAC rights with the project's properties (Linker > Manifest File). "Enable User Account Control" is set to yes, the execution level is set to admin, and the UI protection bypass is set to none. The second way is with ShellExecute. Here's the code: https://pastebin.com/tJLniPbC – PointR Jun 16 '17 at 08:10
  • @PointR - there's a number of points here - first of all as mentioned in my answer, running as administrator does not give you the right to write in protected directories - it merely gives you the right to ask for additional privileges which you can do with AdjustTokenPrivileges. Secondly, if you are getting linking errors trying to call ShellExecute you need to ensure you are actually linking to the right libraries. Have you added Shell32.lib to your dependencies? . – Anthill Jun 16 '17 at 08:19
  • Wow - I wonder what the downvote is about? Not good enough that someone takes time to address someone's question? The least I'd expect would be a comment when downvoting. Shrugs.... – Anthill Jun 16 '17 at 21:06
  • I feel like you're getting the problem Reddit is facing every day: people forget downvoting does not mean "I don't like this." or "I disagree with this." – PointR Jun 17 '17 at 07:53
  • @PointR, it kind of does, though. If the answer is incorrect, that is a perfectly valid reason to downvote. In this case, there was enough evidence in the question to establish that this wasn't the cause of the problem. (I'm not sure why the OP has accepted it. Their latest comment establishes that the problem was 32-bit redirection, not access control.) – Harry Johnston Jun 19 '17 at 21:30
  • ... sorry, didn't realize that you *are* the OP. D'oh! – Harry Johnston Jun 19 '17 at 21:36
  • For the record, anyway, it is *not* true that you need to enable restore privilege to write into system32. I've checked the permissions, and the Administrators group has modify access, which is sufficient to add a new file. (You do need restore privilege to modify the existing files placed there by the operating system, but you shouldn't be doing that anyway.) – Harry Johnston Jun 19 '17 at 21:39
  • I realised it, don't worry. Only I accepted this answer to show this question has been answered, though it was in a comment on the original post. – PointR Jun 20 '17 at 04:25
  • @PointR Hmm in this case you should not accept the answer but either answer it yourself or ask the original commenter to make a new posting with the actual solution (which as I understand it turns out to be 32-bit / 64-bit redirection and your file was landing in SysWow64). Leaving an incorrect answer as accepted is misleading so please "unaccept" the answer if at all possible :) – Anthill Jun 20 '17 at 13:39