1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_desktop.hxx"
30*cdf0e10cSrcweir #define UNICODE
31*cdf0e10cSrcweir #define _UNICODE
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include <cstddef>
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN
36*cdf0e10cSrcweir #if defined _MSC_VER
37*cdf0e10cSrcweir #pragma warning(push, 1)
38*cdf0e10cSrcweir #endif
39*cdf0e10cSrcweir #include <windows.h>
40*cdf0e10cSrcweir #include <shellapi.h>
41*cdf0e10cSrcweir #if defined _MSC_VER
42*cdf0e10cSrcweir #pragma warning(pop)
43*cdf0e10cSrcweir #endif
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir #include <tchar.h>
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir #include <malloc.h>
48*cdf0e10cSrcweir #include <string.h>
49*cdf0e10cSrcweir #include <stdlib.h>
50*cdf0e10cSrcweir #include <systools/win32/uwinapi.h>
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir #include "rtl/string.h"
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir #include "../../../source/inc/exithelper.hxx"
55*cdf0e10cSrcweir #include "../extendloaderenvironment.hxx"
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir #define PIPE_PREFIX					TEXT("\\\\.\\pipe\\OSL_PIPE_")
58*cdf0e10cSrcweir #define	PIPE_POSTFIX				TEXT("_SingleOfficeIPC_")
59*cdf0e10cSrcweir #define PIPE_TERMINATION_SEQUENCE	"InternalIPC::ProcessingDone"
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir BOOL WINAPI ConvertSidToStringSid( PSID pSid, LPTSTR* StringSid )
62*cdf0e10cSrcweir {
63*cdf0e10cSrcweir     PSID_IDENTIFIER_AUTHORITY psia;
64*cdf0e10cSrcweir     DWORD dwSubAuthorities;
65*cdf0e10cSrcweir     DWORD dwSidRev=SID_REVISION;
66*cdf0e10cSrcweir     DWORD dwCounter;
67*cdf0e10cSrcweir     DWORD dwSidSize;
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir     // Validate the binary SID.
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir     if(!IsValidSid(pSid)) return FALSE;
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir     // Get the identifier authority value from the SID.
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir     psia = GetSidIdentifierAuthority(pSid);
76*cdf0e10cSrcweir 
77*cdf0e10cSrcweir     // Get the number of subauthorities in the SID.
78*cdf0e10cSrcweir 
79*cdf0e10cSrcweir     dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir     // Compute the buffer length.
82*cdf0e10cSrcweir     // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
83*cdf0e10cSrcweir 
84*cdf0e10cSrcweir     dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
85*cdf0e10cSrcweir 
86*cdf0e10cSrcweir 	*StringSid = (LPTSTR)LocalAlloc( LMEM_FIXED, dwSidSize );
87*cdf0e10cSrcweir 
88*cdf0e10cSrcweir     // Add 'S' prefix and revision number to the string.
89*cdf0e10cSrcweir 
90*cdf0e10cSrcweir     dwSidSize=wsprintf(*StringSid, TEXT("S-%lu-"), dwSidRev );
91*cdf0e10cSrcweir 
92*cdf0e10cSrcweir     // Add a SID identifier authority to the string.
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir     if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
95*cdf0e10cSrcweir     {
96*cdf0e10cSrcweir         dwSidSize+=wsprintf(*StringSid + lstrlen(*StringSid),
97*cdf0e10cSrcweir                     TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
98*cdf0e10cSrcweir                     (USHORT)psia->Value[0],
99*cdf0e10cSrcweir                     (USHORT)psia->Value[1],
100*cdf0e10cSrcweir                     (USHORT)psia->Value[2],
101*cdf0e10cSrcweir                     (USHORT)psia->Value[3],
102*cdf0e10cSrcweir                     (USHORT)psia->Value[4],
103*cdf0e10cSrcweir                     (USHORT)psia->Value[5]);
104*cdf0e10cSrcweir     }
105*cdf0e10cSrcweir     else
106*cdf0e10cSrcweir     {
107*cdf0e10cSrcweir         dwSidSize+=wsprintf(*StringSid + lstrlen(*StringSid),
108*cdf0e10cSrcweir                     TEXT("%lu"),
109*cdf0e10cSrcweir                     (ULONG)(psia->Value[5]      )   +
110*cdf0e10cSrcweir                     (ULONG)(psia->Value[4] <<  8)   +
111*cdf0e10cSrcweir                     (ULONG)(psia->Value[3] << 16)   +
112*cdf0e10cSrcweir                     (ULONG)(psia->Value[2] << 24)   );
113*cdf0e10cSrcweir     }
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir     // Add SID subauthorities to the string.
116*cdf0e10cSrcweir     //
117*cdf0e10cSrcweir     for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
118*cdf0e10cSrcweir     {
119*cdf0e10cSrcweir         dwSidSize+=wsprintf(*StringSid + dwSidSize, TEXT("-%lu"),
120*cdf0e10cSrcweir                     *GetSidSubAuthority(pSid, dwCounter) );
121*cdf0e10cSrcweir     }
122*cdf0e10cSrcweir 
123*cdf0e10cSrcweir     return TRUE;
124*cdf0e10cSrcweir }
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir 
127*cdf0e10cSrcweir //---------------------------------------------------------------------------
128*cdf0e10cSrcweir 
129*cdf0e10cSrcweir static LPTSTR	*GetCommandArgs( int *pArgc )
130*cdf0e10cSrcweir {
131*cdf0e10cSrcweir #ifdef UNICODE
132*cdf0e10cSrcweir 	return CommandLineToArgvW( GetCommandLineW(), pArgc );
133*cdf0e10cSrcweir #else
134*cdf0e10cSrcweir 	*pArgc = __argc;
135*cdf0e10cSrcweir 	return __argv;
136*cdf0e10cSrcweir #endif
137*cdf0e10cSrcweir }
138*cdf0e10cSrcweir 
139*cdf0e10cSrcweir //---------------------------------------------------------------------------
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir namespace {
142*cdf0e10cSrcweir 
143*cdf0e10cSrcweir bool writeArgument(HANDLE pipe, char prefix, WCHAR const * argument) {
144*cdf0e10cSrcweir     CHAR szBuffer[4096];
145*cdf0e10cSrcweir     int n = WideCharToMultiByte(
146*cdf0e10cSrcweir         CP_UTF8, 0, argument, -1, szBuffer, sizeof (szBuffer), NULL, NULL);
147*cdf0e10cSrcweir     char b[1 + 2 * ((sizeof szBuffer) - 1)]; // hopefully does not overflow
148*cdf0e10cSrcweir     b[0] = prefix;
149*cdf0e10cSrcweir     char * p = b + 1;
150*cdf0e10cSrcweir     for (int i = 0; i < n - 1; ++i) { // cannot underflow (n >= 0)
151*cdf0e10cSrcweir         char c = szBuffer[i];
152*cdf0e10cSrcweir         switch (c) {
153*cdf0e10cSrcweir         case '\0':
154*cdf0e10cSrcweir             *p++ = '\\';
155*cdf0e10cSrcweir             *p++ = '0';
156*cdf0e10cSrcweir             break;
157*cdf0e10cSrcweir         case ',':
158*cdf0e10cSrcweir             *p++ = '\\';
159*cdf0e10cSrcweir             *p++ = ',';
160*cdf0e10cSrcweir             break;
161*cdf0e10cSrcweir         case '\\':
162*cdf0e10cSrcweir             *p++ = '\\';
163*cdf0e10cSrcweir             *p++ = '\\';
164*cdf0e10cSrcweir             break;
165*cdf0e10cSrcweir         default:
166*cdf0e10cSrcweir             *p++ = c;
167*cdf0e10cSrcweir             break;
168*cdf0e10cSrcweir         }
169*cdf0e10cSrcweir     }
170*cdf0e10cSrcweir     DWORD w;
171*cdf0e10cSrcweir     return WriteFile(pipe, b, p - b, &w, NULL);
172*cdf0e10cSrcweir }
173*cdf0e10cSrcweir 
174*cdf0e10cSrcweir }
175*cdf0e10cSrcweir 
176*cdf0e10cSrcweir #ifdef __MINGW32__
177*cdf0e10cSrcweir int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int )
178*cdf0e10cSrcweir #else
179*cdf0e10cSrcweir int WINAPI _tWinMain( HINSTANCE, HINSTANCE, LPTSTR, int )
180*cdf0e10cSrcweir #endif
181*cdf0e10cSrcweir {
182*cdf0e10cSrcweir 	TCHAR				szTargetFileName[MAX_PATH] = TEXT("");
183*cdf0e10cSrcweir     TCHAR               szIniDirectory[MAX_PATH];
184*cdf0e10cSrcweir 	TCHAR				szPerfTuneIniFile[MAX_PATH] = TEXT("");
185*cdf0e10cSrcweir 	STARTUPINFO			aStartupInfo;
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir     desktop_win32::extendLoaderEnvironment(szTargetFileName, szIniDirectory);
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir 	ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) );
190*cdf0e10cSrcweir 	aStartupInfo.cb = sizeof(aStartupInfo);
191*cdf0e10cSrcweir 
192*cdf0e10cSrcweir 	GetStartupInfo( &aStartupInfo );
193*cdf0e10cSrcweir 	// Get image path with same name but with .bin extension
194*cdf0e10cSrcweir 
195*cdf0e10cSrcweir 	TCHAR				szModuleFileName[MAX_PATH];
196*cdf0e10cSrcweir 
197*cdf0e10cSrcweir 	GetModuleFileName( NULL, szModuleFileName, MAX_PATH );
198*cdf0e10cSrcweir 	_TCHAR	*lpLastSlash = _tcsrchr( szModuleFileName, '\\' );
199*cdf0e10cSrcweir 	if ( lpLastSlash )
200*cdf0e10cSrcweir 	{
201*cdf0e10cSrcweir 		size_t len = lpLastSlash - szModuleFileName + 1;
202*cdf0e10cSrcweir 		_tcsncpy( szPerfTuneIniFile, szModuleFileName, len );
203*cdf0e10cSrcweir 		_tcsncpy( szPerfTuneIniFile + len, _T("perftune.ini"), sizeof(szPerfTuneIniFile)/sizeof(szPerfTuneIniFile[0]) - len );
204*cdf0e10cSrcweir 	}
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir 	// Create process with same command line, environment and stdio handles which
207*cdf0e10cSrcweir 	// are directed to the created pipes
208*cdf0e10cSrcweir 
209*cdf0e10cSrcweir 	DWORD	dwExitCode = (DWORD)-1;
210*cdf0e10cSrcweir 
211*cdf0e10cSrcweir 	BOOL	fSuccess = FALSE;
212*cdf0e10cSrcweir 	LPTSTR	lpCommandLine = NULL;
213*cdf0e10cSrcweir     int argc = 0;
214*cdf0e10cSrcweir     LPTSTR * argv = NULL;
215*cdf0e10cSrcweir     bool bFirst = true;
216*cdf0e10cSrcweir     WCHAR cwd[MAX_PATH];
217*cdf0e10cSrcweir     DWORD cwdLen = GetCurrentDirectoryW(MAX_PATH, cwd);
218*cdf0e10cSrcweir     if (cwdLen >= MAX_PATH) {
219*cdf0e10cSrcweir         cwdLen = 0;
220*cdf0e10cSrcweir     }
221*cdf0e10cSrcweir 
222*cdf0e10cSrcweir 	do
223*cdf0e10cSrcweir 	{
224*cdf0e10cSrcweir 		TCHAR	szKey[32];
225*cdf0e10cSrcweir 
226*cdf0e10cSrcweir 		GetPrivateProfileString(
227*cdf0e10cSrcweir 			TEXT("PerformanceTuning"),
228*cdf0e10cSrcweir 			TEXT("FastPipeCommunication"),
229*cdf0e10cSrcweir 			TEXT("0"),
230*cdf0e10cSrcweir 			szKey,
231*cdf0e10cSrcweir 			elementsof(szKey),
232*cdf0e10cSrcweir 			szPerfTuneIniFile
233*cdf0e10cSrcweir 			);
234*cdf0e10cSrcweir 
235*cdf0e10cSrcweir 		if ( 0 == _tcscmp( szKey, TEXT("1") ) )
236*cdf0e10cSrcweir 		{
237*cdf0e10cSrcweir 			HANDLE	hProcessToken;
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir 			if ( OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hProcessToken ) )
240*cdf0e10cSrcweir 			{
241*cdf0e10cSrcweir 				TCHAR	szPipeName[4096];
242*cdf0e10cSrcweir 
243*cdf0e10cSrcweir 
244*cdf0e10cSrcweir 				DWORD	dwTokenLength = 0;
245*cdf0e10cSrcweir 
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir 				fSuccess = GetTokenInformation( hProcessToken, TokenUser, NULL, dwTokenLength, &dwTokenLength );
248*cdf0e10cSrcweir 
249*cdf0e10cSrcweir 				PVOID	pTokenInfo = _alloca(dwTokenLength);
250*cdf0e10cSrcweir 				fSuccess = GetTokenInformation( hProcessToken, TokenUser, pTokenInfo, dwTokenLength, &dwTokenLength );
251*cdf0e10cSrcweir 				CloseHandle( hProcessToken );
252*cdf0e10cSrcweir 
253*cdf0e10cSrcweir 				PSID pSid = ((PTOKEN_USER)pTokenInfo)->User.Sid;
254*cdf0e10cSrcweir 				LPTSTR	szUserIdent = NULL;
255*cdf0e10cSrcweir 				TCHAR	szSUPD[11] = TEXT("0");
256*cdf0e10cSrcweir 
257*cdf0e10cSrcweir 				fSuccess = ConvertSidToStringSid( pSid, &szUserIdent );
258*cdf0e10cSrcweir 
259*cdf0e10cSrcweir 				_tcsncpy( szPipeName, PIPE_PREFIX, elementsof(szPipeName) );
260*cdf0e10cSrcweir 				_tcsncat( szPipeName, szUserIdent, elementsof(szPipeName) - _tcslen(szPipeName) - 1 );
261*cdf0e10cSrcweir 				_tcsncat( szPipeName, PIPE_POSTFIX, elementsof(szPipeName) - _tcslen(szPipeName) - 1 );
262*cdf0e10cSrcweir 				_tcsncat( szPipeName, _ultot( SUPD, szSUPD, 10), elementsof(szPipeName) - _tcslen(szPipeName) - 1 );
263*cdf0e10cSrcweir 
264*cdf0e10cSrcweir 				LocalFree( szUserIdent );
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir 				HANDLE	hPipe = CreateFile(
267*cdf0e10cSrcweir 									szPipeName,
268*cdf0e10cSrcweir 									GENERIC_READ|GENERIC_WRITE,
269*cdf0e10cSrcweir 									FILE_SHARE_READ | FILE_SHARE_WRITE,
270*cdf0e10cSrcweir 									NULL,
271*cdf0e10cSrcweir 									OPEN_EXISTING,
272*cdf0e10cSrcweir 									FILE_ATTRIBUTE_NORMAL,
273*cdf0e10cSrcweir 									NULL);
274*cdf0e10cSrcweir 
275*cdf0e10cSrcweir 				if ( INVALID_HANDLE_VALUE != hPipe )
276*cdf0e10cSrcweir 				{
277*cdf0e10cSrcweir 					DWORD	dwBytesWritten;
278*cdf0e10cSrcweir 					int	argc = 0;
279*cdf0e10cSrcweir 					LPWSTR	*argv = CommandLineToArgvW( GetCommandLine(), &argc );
280*cdf0e10cSrcweir 
281*cdf0e10cSrcweir 					fSuccess = WriteFile( hPipe, RTL_CONSTASCII_STRINGPARAM("InternalIPC::Arguments"), &dwBytesWritten, NULL );
282*cdf0e10cSrcweir                     if (fSuccess) {
283*cdf0e10cSrcweir                         if (cwdLen > 0) {
284*cdf0e10cSrcweir                             fSuccess = writeArgument(hPipe, '2', cwd);
285*cdf0e10cSrcweir                         } else {
286*cdf0e10cSrcweir                             fSuccess = WriteFile(
287*cdf0e10cSrcweir                                 hPipe, RTL_CONSTASCII_STRINGPARAM("0"),
288*cdf0e10cSrcweir                                 &dwBytesWritten, NULL);
289*cdf0e10cSrcweir                         }
290*cdf0e10cSrcweir                     }
291*cdf0e10cSrcweir 					for ( int argn = 1; fSuccess && argn < argc; argn++ )
292*cdf0e10cSrcweir 					{
293*cdf0e10cSrcweir                         fSuccess = writeArgument(hPipe, ',', argv[argn]);
294*cdf0e10cSrcweir 					}
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir 					if ( fSuccess )
297*cdf0e10cSrcweir 					{
298*cdf0e10cSrcweir 						fSuccess = WriteFile(  hPipe, "", 1, &dwBytesWritten, NULL );
299*cdf0e10cSrcweir 						if ( fSuccess )
300*cdf0e10cSrcweir 						{
301*cdf0e10cSrcweir 							DWORD	dwBytesRead = 0;
302*cdf0e10cSrcweir 							char	*pBuffer = (char *)_alloca( sizeof(PIPE_TERMINATION_SEQUENCE) );
303*cdf0e10cSrcweir 							fSuccess = ReadFile( hPipe, pBuffer, sizeof(PIPE_TERMINATION_SEQUENCE) - 1, &dwBytesRead, NULL );
304*cdf0e10cSrcweir 							if ( fSuccess )
305*cdf0e10cSrcweir 							{
306*cdf0e10cSrcweir 								pBuffer[dwBytesRead] = 0;
307*cdf0e10cSrcweir 								if ( 0 != strcmp( PIPE_TERMINATION_SEQUENCE, pBuffer ) )
308*cdf0e10cSrcweir 									fSuccess = FALSE;
309*cdf0e10cSrcweir 							}
310*cdf0e10cSrcweir 						}
311*cdf0e10cSrcweir 					}
312*cdf0e10cSrcweir 
313*cdf0e10cSrcweir 					CloseHandle( hPipe );
314*cdf0e10cSrcweir 
315*cdf0e10cSrcweir 					return fSuccess ? 0 : -1;
316*cdf0e10cSrcweir 				}
317*cdf0e10cSrcweir 
318*cdf0e10cSrcweir 			}
319*cdf0e10cSrcweir 		}
320*cdf0e10cSrcweir 
321*cdf0e10cSrcweir         if ( bFirst ) {
322*cdf0e10cSrcweir             argv = GetCommandArgs(&argc);
323*cdf0e10cSrcweir             std::size_t n = wcslen(argv[0]) + 2;
324*cdf0e10cSrcweir             for (int i = 1; i < argc; ++i) {
325*cdf0e10cSrcweir                 n += wcslen(argv[i]) + 3;
326*cdf0e10cSrcweir             }
327*cdf0e10cSrcweir             n += MY_LENGTH(L" \"-env:OOO_CWD=2") + 4 * cwdLen +
328*cdf0e10cSrcweir                 MY_LENGTH(L"\"") + 1;
329*cdf0e10cSrcweir                 // 4 * cwdLen: each char preceded by backslash, each trailing
330*cdf0e10cSrcweir                 // backslash doubled
331*cdf0e10cSrcweir             lpCommandLine = new WCHAR[n];
332*cdf0e10cSrcweir         }
333*cdf0e10cSrcweir         WCHAR * p = desktop_win32::commandLineAppend(
334*cdf0e10cSrcweir             lpCommandLine, MY_STRING(L"\""));
335*cdf0e10cSrcweir         p = desktop_win32::commandLineAppend(p, argv[0]);
336*cdf0e10cSrcweir         for (int i = 1; i < argc; ++i) {
337*cdf0e10cSrcweir             if (bFirst || ::desktop::ExitHelper::E_NORMAL_RESTART == dwExitCode || wcsncmp(argv[i], MY_STRING(L"-env:")) == 0) {
338*cdf0e10cSrcweir                 p = desktop_win32::commandLineAppend(p, MY_STRING(L"\" \""));
339*cdf0e10cSrcweir                 p = desktop_win32::commandLineAppend(p, argv[i]);
340*cdf0e10cSrcweir             }
341*cdf0e10cSrcweir         }
342*cdf0e10cSrcweir 
343*cdf0e10cSrcweir         p = desktop_win32::commandLineAppend(
344*cdf0e10cSrcweir             p, MY_STRING(L"\" \"-env:OOO_CWD="));
345*cdf0e10cSrcweir         if (cwdLen == 0) {
346*cdf0e10cSrcweir             p = desktop_win32::commandLineAppend(p, MY_STRING(L"0"));
347*cdf0e10cSrcweir         } else {
348*cdf0e10cSrcweir             p = desktop_win32::commandLineAppend(p, MY_STRING(L"2"));
349*cdf0e10cSrcweir             p = desktop_win32::commandLineAppendEncoded(p, cwd);
350*cdf0e10cSrcweir         }
351*cdf0e10cSrcweir         desktop_win32::commandLineAppend(p, MY_STRING(L"\""));
352*cdf0e10cSrcweir         bFirst = false;
353*cdf0e10cSrcweir 
354*cdf0e10cSrcweir 		TCHAR	szParentProcessId[64]; // This is more than large enough for a 128 bit decimal value
355*cdf0e10cSrcweir 		BOOL    bHeadlessMode( FALSE );
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir         {
358*cdf0e10cSrcweir             // Check command line arguments for "-headless" parameter. We only
359*cdf0e10cSrcweir             // set the environment variable "ATTACHED_PARENT_PROCESSID" for the headless
360*cdf0e10cSrcweir             // mode as self-destruction of the soffice.bin process can lead to
361*cdf0e10cSrcweir             // certain side-effects (log-off can result in data-loss, ".lock" is not deleted.
362*cdf0e10cSrcweir             // See 138244 for more information.
363*cdf0e10cSrcweir             int		argc;
364*cdf0e10cSrcweir 		    LPTSTR	*argv = GetCommandArgs( &argc );
365*cdf0e10cSrcweir 
366*cdf0e10cSrcweir 		    if ( argc > 1 )
367*cdf0e10cSrcweir 		    {
368*cdf0e10cSrcweir 			    int n;
369*cdf0e10cSrcweir 
370*cdf0e10cSrcweir 			    for ( n = 1; n < argc; n++ )
371*cdf0e10cSrcweir 			    {
372*cdf0e10cSrcweir 		            if ( 0 == _tcsnicmp( argv[n], _T("-headless"), 9 ) )
373*cdf0e10cSrcweir                         bHeadlessMode = TRUE;
374*cdf0e10cSrcweir 			    }
375*cdf0e10cSrcweir             }
376*cdf0e10cSrcweir         }
377*cdf0e10cSrcweir 
378*cdf0e10cSrcweir         if ( _ltot( (long)GetCurrentProcessId(),szParentProcessId, 10 ) && bHeadlessMode )
379*cdf0e10cSrcweir 			SetEnvironmentVariable( TEXT("ATTACHED_PARENT_PROCESSID"), szParentProcessId );
380*cdf0e10cSrcweir 
381*cdf0e10cSrcweir 		PROCESS_INFORMATION	aProcessInfo;
382*cdf0e10cSrcweir 
383*cdf0e10cSrcweir 		fSuccess = CreateProcess(
384*cdf0e10cSrcweir 			szTargetFileName,
385*cdf0e10cSrcweir 			lpCommandLine,
386*cdf0e10cSrcweir 			NULL,
387*cdf0e10cSrcweir 			NULL,
388*cdf0e10cSrcweir 			TRUE,
389*cdf0e10cSrcweir 			0,
390*cdf0e10cSrcweir 			NULL,
391*cdf0e10cSrcweir 			szIniDirectory,
392*cdf0e10cSrcweir 			&aStartupInfo,
393*cdf0e10cSrcweir 			&aProcessInfo );
394*cdf0e10cSrcweir 
395*cdf0e10cSrcweir 		if ( fSuccess )
396*cdf0e10cSrcweir 		{
397*cdf0e10cSrcweir 			DWORD	dwWaitResult;
398*cdf0e10cSrcweir 
399*cdf0e10cSrcweir 			do
400*cdf0e10cSrcweir 			{
401*cdf0e10cSrcweir 				// On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWidth" so we have to do so
402*cdf0e10cSrcweir 				// as if we where processing any messages
403*cdf0e10cSrcweir 
404*cdf0e10cSrcweir 				dwWaitResult = MsgWaitForMultipleObjects( 1, &aProcessInfo.hProcess, FALSE, INFINITE, QS_ALLEVENTS );
405*cdf0e10cSrcweir 
406*cdf0e10cSrcweir 				if (  WAIT_OBJECT_0 + 1 == dwWaitResult )
407*cdf0e10cSrcweir 				{
408*cdf0e10cSrcweir 					MSG	msg;
409*cdf0e10cSrcweir 
410*cdf0e10cSrcweir 					PeekMessage( &msg, NULL, 0, 0, PM_REMOVE );
411*cdf0e10cSrcweir 				}
412*cdf0e10cSrcweir 			} while ( WAIT_OBJECT_0 + 1 == dwWaitResult );
413*cdf0e10cSrcweir 
414*cdf0e10cSrcweir 			dwExitCode = 0;
415*cdf0e10cSrcweir 			GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode );
416*cdf0e10cSrcweir 
417*cdf0e10cSrcweir 			CloseHandle( aProcessInfo.hProcess );
418*cdf0e10cSrcweir 			CloseHandle( aProcessInfo.hThread );
419*cdf0e10cSrcweir 		}
420*cdf0e10cSrcweir 	} while ( fSuccess
421*cdf0e10cSrcweir               && ( ::desktop::ExitHelper::E_CRASH_WITH_RESTART == dwExitCode || ::desktop::ExitHelper::E_NORMAL_RESTART == dwExitCode ));
422*cdf0e10cSrcweir     delete[] lpCommandLine;
423*cdf0e10cSrcweir 
424*cdf0e10cSrcweir 	return fSuccess ? dwExitCode : -1;
425*cdf0e10cSrcweir }
426