+1  A: 

I don't see any reference in the CreateProcess documentation saying that the '\\?\' syntax is valid for the module name. The page on "Naming a File or Directory" also does not state that CreateProcess supports it, while functions such as CreateFile link to the "Naming a File" page.

I do see that you can't use a module name longer than MAX_PATH in lpCommandLine, which suggests that CreateProcess does not support extra long filenames. The error message also suggests that an error is occurring while attempting to append ".manifest" to your application path (that is, the length is now exceeding MAX_PATH).

GetShortPathName() may be of some help here, though it does not guarantee to return a name less than MAX_PATH (it does explicitly state that '\\?\' syntax is valid, though). Otherwise, you could try adjusting the PATH environment variable and passing it to CreateProcess() in lpEnvironment. Or you could use SetCurrentDirectory() and pass only the executable name.

Zooba
+1  A: 

Embedding the manifest and using GetShortPathNameW did it for me. One or the other on their own wasn't enough.

Before calling CreateProcessW using the \\?-prefixed absolute path name of the process to execute as the first argument, I check:

wchar_t *w_argv0;
wchar_t *w_short_argv0;

...

if (wcslen(w_argv0) >= MAX_PATH)
{
    num_chars = GetShortPathNameW(w_argv0,NULL,0);
    if (num_chars == 0) {
        syslog(LOG_ERR,"GetShortPathName(%S) to get size failed (%d)",
w_argv0,GetLastError()); /* ** Might as well keep going and try with the long name */ } else { w_short_argv0 = malloc(num_chars * sizeof(wchar_t)); memset(w_short_argv0,0,num_chars * sizeof(wchar_t)); if (GetShortPathNameW(w_argv0,w_short_argv0,num_chars) == 0) { syslog(LOG_ERR,"GetShortPathName(%S) failed (%d)",w_argv0,
GetLastError()); free(w_short_argv0); w_short_argv0 = NULL; } else { syslog(LOG_DEBUG,"using short name %S for %S",w_short_argv0,
w_argv0); } } }

and then call CreateProcessW(w_short_argv0 ? w_short_argv0 : w_argv0...);

remembering to free(w_short_argv0); afterwards.

This may not solve every case, but it lets me spawn more child processes than I could before.

dbyron