BOOL GLDProcessFunc::startProcess(const string &strExe, const list<string> ¶ms) { string args = createCommandLine(strExe, params); BOOL success = false; PROCESS_INFORMATION pinfo; STARTUPINFOW startupInfo = { sizeof(STARTUPINFO), 0, 0, 0, (DWORD)CW_USEDEFAULT, (DWORD)CW_USEDEFAULT, (DWORD)CW_USEDEFAULT, (DWORD)CW_USEDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; wstring widestr = std::wstring(args.begin(), args.end()); success = CreateProcess(0, const_cast<wchar_t *>(widestr.c_str()), 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0, 0, &startupInfo, &pinfo); if (success) { CloseHandle(pinfo.hThread); CloseHandle(pinfo.hProcess); } return success; }
/* * The main function implements a loader for applications which use UNO. * * <p>This code runs on the Windows platform only.</p> * * <p>The main function detects a UNO installation on the system and adds the * program directory of the UNO installation to the PATH environment variable. * After that, the application process is loaded and started, whereby the * new process inherits the environment of the calling process, including * the modified PATH environment variable. The application's executable name * must be the same as the name of this executable, prefixed by '_'.</p> * * <p>A UNO installation can be specified by the user by setting the UNO_PATH * environment variable to the program directory of the UNO installation. * If no installation is specified by the user, the default installation on * the system will be taken. The default installation is read from the * default value of the key "Software\LibreOffice\UNO\InstallPath" from the * root key HKEY_CURRENT_USER in the Windows Registry. If this key is missing, * the key is read from the root key HKEY_LOCAL_MACHINE.</p> */ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { const char* ENVVARNAME = "PATH"; const char* PATHSEPARATOR = ";"; char const* path = NULL; char path2[MAX_PATH]; char* value = NULL; char* envstr = NULL; char* cmdline = NULL; size_t size; STARTUPINFO startup_info; PROCESS_INFORMATION process_info; BOOL bCreate; (void) hInstance; /* unused */ (void) hPrevInstance; /* unused */ (void) nCmdShow; /* unused */ /* get the path of the UNO installation */ path = getPath(); if ( path != NULL ) { wchar_t cmd[ MY_LENGTH(L"\"") + MAX_PATH + MY_LENGTH(L"\\unoinfo.exe\" c++")]; /* hopefully does not overflow */ int pathsize; SECURITY_ATTRIBUTES sec; HANDLE temp; HANDLE stdoutRead; HANDLE stdoutWrite; STARTUPINFOW startinfo; PROCESS_INFORMATION procinfo; int ret; cmd[0] = L'"'; pathsize = MultiByteToWideChar(CP_ACP, 0, path, -1, cmd + 1, MAX_PATH); if (pathsize == 0) { writeError("Error: MultiByteToWideChar failed!\n"); closeErrorFile(); return 1; } if (wcschr(cmd + 1, L'"') != NULL) { writeError("Error: bad characters in UNO installation path!\n"); closeErrorFile(); return 1; } wcscpy( cmd + pathsize, (L"\\unoinfo.exe\" c++" + (pathsize == 1 || cmd[pathsize - 1] != L'\\' ? 0 : 1))); sec.nLength = sizeof (SECURITY_ATTRIBUTES); sec.lpSecurityDescriptor = NULL; sec.bInheritHandle = TRUE; if (CreatePipe(&temp, &stdoutWrite, &sec, 0) == 0 || DuplicateHandle( GetCurrentProcess(), temp, GetCurrentProcess(), &stdoutRead, 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS) == 0) { writeError("Error: CreatePipe/DuplicateHandle failed!\n"); closeErrorFile(); return 1; } memset(&startinfo, 0, sizeof (STARTUPINFOW)); startinfo.cb = sizeof (STARTUPINFOW); startinfo.lpDesktop = L""; startinfo.dwFlags = STARTF_USESTDHANDLES; startinfo.hStdOutput = stdoutWrite; ret = CreateProcessW( NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &startinfo, &procinfo); if (ret != 0) { char * buf = NULL; char * tmp; DWORD n = 1000; DWORD k = 0; DWORD exitcode; int path2size; CloseHandle(stdoutWrite); CloseHandle(procinfo.hThread); for (;;) { DWORD m; tmp = realloc(buf, n); if (tmp == NULL) { free(buf); writeError( "Error: out of memory reading unoinfo output!\n"); closeErrorFile(); return 1; } buf = tmp; if (!ReadFile(stdoutRead, buf + k, n - k, &m, NULL)) { DWORD err = GetLastError(); if (err == ERROR_HANDLE_EOF || err == ERROR_BROKEN_PIPE) { break; } writeError("Error: cannot read unoinfo output!\n"); closeErrorFile(); return 1; } if (m == 0) { break; } k += m; if (k >= n) { if (n >= MAXDWORD / 2) { writeError( "Error: out of memory reading unoinfo output!\n"); closeErrorFile(); return 1; } n *= 2; } } if ((k & 1) == 1) { writeError("Error: bad unoinfo output!\n"); closeErrorFile(); return 1; } CloseHandle(stdoutRead); if (!GetExitCodeProcess(procinfo.hProcess, &exitcode) || exitcode != 0) { writeError("Error: executing unoinfo failed!\n"); closeErrorFile(); return 1; } if (k == 0) { path2size = 0; } else { path2size = WideCharToMultiByte( CP_ACP, 0, (wchar_t *) buf, k / 2, path2, MAX_PATH - 1, NULL, NULL); if (path2size == 0) { writeError("Error: converting unoinfo output failed!\n"); closeErrorFile(); return 1; } } path2[path2size] = '\0'; path = path2; } else { if (GetLastError() != ERROR_FILE_NOT_FOUND) { writeError("Error: calling unoinfo failed!\n"); closeErrorFile(); return 1; } CloseHandle(stdoutRead); CloseHandle(stdoutWrite); } /* get the value of the PATH environment variable */ value = getenv( ENVVARNAME ); /* * add the UNO installation path to the PATH environment variable; * note that this only affects the environment variable of the current * process, the command processor's environment is not changed */ size = strlen( ENVVARNAME ) + strlen( "=" ) + strlen( path ) + 1; if ( value != NULL ) size += strlen( PATHSEPARATOR ) + strlen( value ); envstr = (char*) malloc( size ); strcpy( envstr, ENVVARNAME ); strcat( envstr, "=" ); strcat( envstr, path ); if ( value != NULL ) { strcat( envstr, PATHSEPARATOR ); strcat( envstr, value ); } _putenv( envstr ); free( envstr ); } else { writeError( "Warning: no UNO installation found!\n" ); } /* create the command line for the application process */ cmdline = createCommandLine( lpCmdLine ); if ( cmdline == NULL ) { writeError( "Error: cannot create command line!\n" ); closeErrorFile(); return 1; } /* create the application process */ memset( &startup_info, 0, sizeof( STARTUPINFO ) ); startup_info.cb = sizeof( STARTUPINFO ); bCreate = CreateProcess( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup_info, &process_info ); free( cmdline ); if ( !bCreate ) { writeError( "Error: cannot create process!\n" ); closeErrorFile(); return 1; } /* close the error file */ closeErrorFile(); return 0; }