views:

367

answers:

1

On Windows XP and Vista, I can run this code:

STARTUPINFO si;
PROCESS_INFORMATION pi;
BOOL bResult = FALSE;

ZeroMemory(&pi, sizeof(pi));

ZeroMemory(&si, sizeof(si));

si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;

bResult = CreateProcess(NULL, 
                        "rundll32.exe shell32.dll,Control_RunDLL modem.cpl", 
                        NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, 
                        &si, &pi);

if (bResult)
{
    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

and it operates as I would expect, i.e. the WaitForSingleObject does not return until the Modem Control Panel window has been closed by the user.

On Windows 7, the same code, WaitForSingleObject returns straight away (with a return code of 0 indicating that the object signalled the requested state).

Similarly, if I take it to the command line, on XP and Vista I can run

start /wait rundll32.exe shell32.dll,Control_RunDLL modem.cpl

and it does not return control to the command prompt until the Control Panel window is closed, but on Windows 7 it returns immediately.

Is this a change in RunDll32? I know MS made some changes to RunDll32 in Windows 7 for UAC, and it looks from these experiments as though one of those changes might have involved spawning an additional process to display the window, and allowing the originating process to exit. The only thing that makes me think this might not be the case is that using a process explorer that shows the creation and destruction of processes, I do not see anything additional being created beyond the called rundll32 process itself.

Any other way I can solve this? I just don't want the function to return until the control panel window is closed.

A: 

In case anyone else stumbles on the same problem: I finally worked around this with some help from Microsoft Tech Support.

They were able to confirm that the original RunDll32 process is still running (it hasn't spawned a new process) but for whatever reason that they don't know the answer to, WaitForSingleObject() is returning immediately on that process.

The workaround is to fire off the control panel window differently, using CPLApplet as in this example: http://support.microsoft.com/kb/232536

However the issue is complicated further by the fact that the 32-bit modem control panel doesn't work in 64-bit Windows (it displays but "Add" button has no effect). I was already turning off WOW64 redirection in my RunDLL solution on 64-bit platforms, and that worked fine, but you can't load a 64-bit library in a 32-bit app so I had to spawn a new process to do this.

In summary:

Win 7 64 bit: call CPLApplet via CreateProcess in 64-bit executable
Win 7 32 bit: call CPLApplet within my installer
XP / Vista 64 bit: turn off WOW64 redirection, use RunDll32
XP / Vista 32 bit: use RunDll32
Vicky