0

I have a 32bit application that must call C:\Windows\System32\regedit.exe, but instead it runs C:\Windows\SysWOW64\regedit.exe. How can I call the regedit in System32?

void CSecureShellView::OnCommandsRegistry64bit()
{
    STARTUPINFO          si = { sizeof(si) };
    PROCESS_INFORMATION  pi;
    CString szExe;
    szExe = "regedit.exe";
        
    if (CreateProcess("C:\\Windows\\Sysnative\\cmd.exe", szExe.GetBuffer(100), 0, 0, FALSE, CREATE_NO_WINDOW, 0, 0, &si, &pi))
    {
        WaitForSingleObject(pi.hProcess, IGNORE);// optionally wait for process to finish

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }
}

The Condition returns True but regedit does not run.

Instead of SysNative, I put System32, but it does not work. In szExe, I put the string "C:\Windows\regedit", but it does not work. And so on ...

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Yahya
  • 35
  • 8
  • 2
    have you tried `C:\\Windows\\Sysnative\\regedit.exe` instead of `regedit.exe`? – Alan Birtles Jun 15 '21 at 17:02
  • https://stackoverflow.com/questions/162309/how-to-launch-a-windows-process-as-64-bit-from-32-bit-code – Mike Vine Jun 15 '21 at 17:18
  • `regedit.exe` is a GUI app, what is the point of running it without a window? If you just want to manipulate the contents of the Registry, there is a [Registry API](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry) for that purpose. – Remy Lebeau Jun 15 '21 at 18:18

2 Answers2

0

You are trying to run regedit.exe via cmd.exe, why? Any result you get will be for cmd.exe, regardless of what commands it executes.

Just run the Registry Editor instead of cmd.exe. However, there is a wrinkle.

The 64bit C:\Windows\System32 folder does not have a regedit.exe executable. The 64bit regedit.exe is located in C:\Windows instead. If a 32bit process tries to run that executable directly, the 32bit C:\Windows\SysWOW64\regedit.exe will be run, which you don't want.

In order for a 32bit process to run the 64bit regedit.exe, it needs to run C:\Windows\Sysnative\Regedt32.exe instead, which is a stub that will run the 64bit C:\Windows\regedit.exe:

void CSecureShellView::OnCommandsRegistry64bit()
{
    STARTUPINFO          si = { sizeof(si) };
    PROCESS_INFORMATION  pi;
    CString szExe = "C:\\Windows\\Sysnative\\Regedt32.exe";
        
    if (CreateProcess(NULL, szExe.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
    {
        WaitForSingleObject(pi.hProcess, INFINITE); // optionally wait for process to finish

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }
}

If CreateProcess() fails with ERROR_ELEVATION_REQUIRED, and you don't want to run your 32bit process elevated, then try using ShellExecute/Ex() with the runas" verb to launch Regedt32.exe elevated.

That being said, you should not hard-code the path to the Windows installation folder. Ask Windows where it is actually installed, such as via GetWindowsDirectory(), SHGetFolderPath(CSIDL_WINDOWS), SHGetKnownFolderPath(FOLDERID_Windows), etc. And then you can append Sysnative\\Regedt32.exe to the end of that path.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • First Thanks for your answer. I use the code but the if condition returns false so the rest of code does not run. I really confuse – Yahya Jun 19 '21 at 04:49
  • @Yahya per the [documentation](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa): "*If the function fails, the return value is zero. **To get extended error information, call [GetLastError](https://learn.microsoft.com/en-us/windows/desktop/api/errhandlingapi/nf-errhandlingapi-getlasterror)**.*" So, what does `GetLastError()` return when `CreateProcess()` fails? – Remy Lebeau Jun 19 '21 at 04:56
  • If the string is "C:\\Windows\\Sysnative\\regedit.exe" the error message is "The System Can not Find The File specified." but if i change the path to "C:\\Windows\\regedit.exe" or "C:\\Windows\\system32\\regedit.exe" the message is "The requested Operation Requires elevation." – Yahya Jun 19 '21 at 07:31
  • Thanks for your answer. It did not work so i solve my problem with another function. – Yahya Jun 21 '21 at 04:59
0

To solve this problem I use ShellExecuteEx() and SHELLEXECUTEINFO.

HRESULT result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
SHELLEXECUTEINFO Sei;
ZeroMemory(&Sei,sizeof(SHELLEXECUTEINFO));
Sei.cbSize = sizeof(SHELLEXECUTEINFO);
Sei.lpFile = "C:\\windows\\regedit.exe";
Sei.nShow = SW_SHOW;
Sei.fMask = SEE_MASK_INVOKEIDLIST;
Sei.lpVerb = "open";
ShellExecuteEx(&Sei);
if (result == S_OK || result == S_FALSE)
    CoUninitialize();

For reference: Launching Applications

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Yahya
  • 35
  • 8