1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: officeloader.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_desktop.hxx"
38 #define WIN32_LEAN_AND_MEAN
40 #pragma warning(push, 1)
53 #include <systools/win32/uwinapi.h>
55 #include "rtl/string.h"
57 #include "../../../source/inc/exithelper.hxx"
58 #include "../extendloaderenvironment.hxx"
60 #define PIPE_PREFIX TEXT("\\\\.\\pipe\\OSL_PIPE_")
61 #define PIPE_POSTFIX TEXT("_SingleOfficeIPC_")
62 #define PIPE_TERMINATION_SEQUENCE "InternalIPC::ProcessingDone"
64 BOOL WINAPI
ConvertSidToStringSid( PSID pSid
, LPTSTR
* StringSid
)
66 PSID_IDENTIFIER_AUTHORITY psia
;
67 DWORD dwSubAuthorities
;
68 DWORD dwSidRev
=SID_REVISION
;
72 // Validate the binary SID.
74 if(!IsValidSid(pSid
)) return FALSE
;
76 // Get the identifier authority value from the SID.
78 psia
= GetSidIdentifierAuthority(pSid
);
80 // Get the number of subauthorities in the SID.
82 dwSubAuthorities
= *GetSidSubAuthorityCount(pSid
);
84 // Compute the buffer length.
85 // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
87 dwSidSize
=(15 + 12 + (12 * dwSubAuthorities
) + 1) * sizeof(TCHAR
);
89 *StringSid
= (LPTSTR
)LocalAlloc( LMEM_FIXED
, dwSidSize
);
91 // Add 'S' prefix and revision number to the string.
93 dwSidSize
=wsprintf(*StringSid
, TEXT("S-%lu-"), dwSidRev
);
95 // Add a SID identifier authority to the string.
97 if ( (psia
->Value
[0] != 0) || (psia
->Value
[1] != 0) )
99 dwSidSize
+=wsprintf(*StringSid
+ lstrlen(*StringSid
),
100 TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
101 (USHORT
)psia
->Value
[0],
102 (USHORT
)psia
->Value
[1],
103 (USHORT
)psia
->Value
[2],
104 (USHORT
)psia
->Value
[3],
105 (USHORT
)psia
->Value
[4],
106 (USHORT
)psia
->Value
[5]);
110 dwSidSize
+=wsprintf(*StringSid
+ lstrlen(*StringSid
),
112 (ULONG
)(psia
->Value
[5] ) +
113 (ULONG
)(psia
->Value
[4] << 8) +
114 (ULONG
)(psia
->Value
[3] << 16) +
115 (ULONG
)(psia
->Value
[2] << 24) );
118 // Add SID subauthorities to the string.
120 for (dwCounter
=0 ; dwCounter
< dwSubAuthorities
; dwCounter
++)
122 dwSidSize
+=wsprintf(*StringSid
+ dwSidSize
, TEXT("-%lu"),
123 *GetSidSubAuthority(pSid
, dwCounter
) );
130 //---------------------------------------------------------------------------
132 static LPTSTR
*GetCommandArgs( int *pArgc
)
135 return CommandLineToArgvW( GetCommandLineW(), pArgc
);
142 //---------------------------------------------------------------------------
146 bool writeArgument(HANDLE pipe
, char prefix
, WCHAR
const * argument
) {
148 int n
= WideCharToMultiByte(
149 CP_UTF8
, 0, argument
, -1, szBuffer
, sizeof (szBuffer
), NULL
, NULL
);
150 char b
[1 + 2 * ((sizeof szBuffer
) - 1)]; // hopefully does not overflow
153 for (int i
= 0; i
< n
- 1; ++i
) { // cannot underflow (n >= 0)
154 char c
= szBuffer
[i
];
174 return WriteFile(pipe
, b
, p
- b
, &w
, NULL
);
180 int WINAPI
WinMain( HINSTANCE hInstance
, HINSTANCE
, LPSTR
, int )
182 int WINAPI
_tWinMain( HINSTANCE
, HINSTANCE
, LPTSTR
, int )
185 TCHAR szTargetFileName
[MAX_PATH
] = TEXT("");
186 TCHAR szIniDirectory
[MAX_PATH
];
187 TCHAR szPerfTuneIniFile
[MAX_PATH
] = TEXT("");
188 STARTUPINFO aStartupInfo
;
190 desktop_win32::extendLoaderEnvironment(szTargetFileName
, szIniDirectory
);
192 ZeroMemory( &aStartupInfo
, sizeof(aStartupInfo
) );
193 aStartupInfo
.cb
= sizeof(aStartupInfo
);
195 GetStartupInfo( &aStartupInfo
);
196 // Get image path with same name but with .bin extension
198 TCHAR szModuleFileName
[MAX_PATH
];
200 GetModuleFileName( NULL
, szModuleFileName
, MAX_PATH
);
201 _TCHAR
*lpLastSlash
= _tcsrchr( szModuleFileName
, '\\' );
204 size_t len
= lpLastSlash
- szModuleFileName
+ 1;
205 _tcsncpy( szPerfTuneIniFile
, szModuleFileName
, len
);
206 _tcsncpy( szPerfTuneIniFile
+ len
, _T("perftune.ini"), sizeof(szPerfTuneIniFile
)/sizeof(szPerfTuneIniFile
[0]) - len
);
209 // Create process with same command line, environment and stdio handles which
210 // are directed to the created pipes
212 DWORD dwExitCode
= (DWORD
)-1;
214 BOOL fSuccess
= FALSE
;
215 LPTSTR lpCommandLine
= NULL
;
217 LPTSTR
* argv
= NULL
;
220 DWORD cwdLen
= GetCurrentDirectoryW(MAX_PATH
, cwd
);
221 if (cwdLen
>= MAX_PATH
) {
229 GetPrivateProfileString(
230 TEXT("PerformanceTuning"),
231 TEXT("FastPipeCommunication"),
238 if ( 0 == _tcscmp( szKey
, TEXT("1") ) )
240 HANDLE hProcessToken
;
242 if ( OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY
, &hProcessToken
) )
244 TCHAR szPipeName
[4096];
247 DWORD dwTokenLength
= 0;
250 fSuccess
= GetTokenInformation( hProcessToken
, TokenUser
, NULL
, dwTokenLength
, &dwTokenLength
);
252 PVOID pTokenInfo
= _alloca(dwTokenLength
);
253 fSuccess
= GetTokenInformation( hProcessToken
, TokenUser
, pTokenInfo
, dwTokenLength
, &dwTokenLength
);
254 CloseHandle( hProcessToken
);
256 PSID pSid
= ((PTOKEN_USER
)pTokenInfo
)->User
.Sid
;
257 LPTSTR szUserIdent
= NULL
;
258 TCHAR szSUPD
[11] = TEXT("0");
260 fSuccess
= ConvertSidToStringSid( pSid
, &szUserIdent
);
262 _tcsncpy( szPipeName
, PIPE_PREFIX
, elementsof(szPipeName
) );
263 _tcsncat( szPipeName
, szUserIdent
, elementsof(szPipeName
) - _tcslen(szPipeName
) - 1 );
264 _tcsncat( szPipeName
, PIPE_POSTFIX
, elementsof(szPipeName
) - _tcslen(szPipeName
) - 1 );
265 _tcsncat( szPipeName
, _ultot( SUPD
, szSUPD
, 10), elementsof(szPipeName
) - _tcslen(szPipeName
) - 1 );
267 LocalFree( szUserIdent
);
269 HANDLE hPipe
= CreateFile(
271 GENERIC_READ
|GENERIC_WRITE
,
272 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
275 FILE_ATTRIBUTE_NORMAL
,
278 if ( INVALID_HANDLE_VALUE
!= hPipe
)
280 DWORD dwBytesWritten
;
282 LPWSTR
*argv
= CommandLineToArgvW( GetCommandLine(), &argc
);
284 fSuccess
= WriteFile( hPipe
, RTL_CONSTASCII_STRINGPARAM("InternalIPC::Arguments"), &dwBytesWritten
, NULL
);
287 fSuccess
= writeArgument(hPipe
, '2', cwd
);
289 fSuccess
= WriteFile(
290 hPipe
, RTL_CONSTASCII_STRINGPARAM("0"),
291 &dwBytesWritten
, NULL
);
294 for ( int argn
= 1; fSuccess
&& argn
< argc
; argn
++ )
296 fSuccess
= writeArgument(hPipe
, ',', argv
[argn
]);
301 fSuccess
= WriteFile( hPipe
, "", 1, &dwBytesWritten
, NULL
);
304 DWORD dwBytesRead
= 0;
305 char *pBuffer
= (char *)_alloca( sizeof(PIPE_TERMINATION_SEQUENCE
) );
306 fSuccess
= ReadFile( hPipe
, pBuffer
, sizeof(PIPE_TERMINATION_SEQUENCE
) - 1, &dwBytesRead
, NULL
);
309 pBuffer
[dwBytesRead
] = 0;
310 if ( 0 != strcmp( PIPE_TERMINATION_SEQUENCE
, pBuffer
) )
316 CloseHandle( hPipe
);
318 return fSuccess
? 0 : -1;
325 argv
= GetCommandArgs(&argc
);
326 std::size_t n
= wcslen(argv
[0]) + 2;
327 for (int i
= 1; i
< argc
; ++i
) {
328 n
+= wcslen(argv
[i
]) + 3;
330 n
+= MY_LENGTH(L
" \"-env:OOO_CWD=2") + 4 * cwdLen
+
331 MY_LENGTH(L
"\"") + 1;
332 // 4 * cwdLen: each char preceded by backslash, each trailing
334 lpCommandLine
= new WCHAR
[n
];
336 WCHAR
* p
= desktop_win32::commandLineAppend(
337 lpCommandLine
, MY_STRING(L
"\""));
338 p
= desktop_win32::commandLineAppend(p
, argv
[0]);
339 for (int i
= 1; i
< argc
; ++i
) {
340 if (first
|| wcsncmp(argv
[i
], MY_STRING(L
"-env:")) == 0) {
341 p
= desktop_win32::commandLineAppend(p
, MY_STRING(L
"\" \""));
342 p
= desktop_win32::commandLineAppend(p
, argv
[i
]);
345 p
= desktop_win32::commandLineAppend(
346 p
, MY_STRING(L
"\" \"-env:OOO_CWD="));
348 p
= desktop_win32::commandLineAppend(p
, MY_STRING(L
"0"));
350 p
= desktop_win32::commandLineAppend(p
, MY_STRING(L
"2"));
351 p
= desktop_win32::commandLineAppendEncoded(p
, cwd
);
353 desktop_win32::commandLineAppend(p
, MY_STRING(L
"\""));
356 TCHAR szParentProcessId
[64]; // This is more than large enough for a 128 bit decimal value
357 BOOL
bHeadlessMode( FALSE
);
360 // Check command line arguments for "-headless" parameter. We only
361 // set the environment variable "ATTACHED_PARENT_PROCESSID" for the headless
362 // mode as self-destruction of the soffice.bin process can lead to
363 // certain side-effects (log-off can result in data-loss, ".lock" is not deleted.
364 // See 138244 for more information.
366 LPTSTR
*argv
= GetCommandArgs( &argc
);
372 for ( n
= 1; n
< argc
; n
++ )
374 if ( 0 == _tcsnicmp( argv
[n
], _T("-headless"), 9 ) )
375 bHeadlessMode
= TRUE
;
380 if ( _ltot( (long)GetCurrentProcessId(),szParentProcessId
, 10 ) && bHeadlessMode
)
381 SetEnvironmentVariable( TEXT("ATTACHED_PARENT_PROCESSID"), szParentProcessId
);
383 PROCESS_INFORMATION aProcessInfo
;
385 fSuccess
= CreateProcess(
403 // On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWidth" so we have to do so
404 // as if we where processing any messages
406 dwWaitResult
= MsgWaitForMultipleObjects( 1, &aProcessInfo
.hProcess
, FALSE
, INFINITE
, QS_ALLEVENTS
);
408 if ( WAIT_OBJECT_0
+ 1 == dwWaitResult
)
412 PeekMessage( &msg
, NULL
, 0, 0, PM_REMOVE
);
414 } while ( WAIT_OBJECT_0
+ 1 == dwWaitResult
);
417 GetExitCodeProcess( aProcessInfo
.hProcess
, &dwExitCode
);
419 CloseHandle( aProcessInfo
.hProcess
);
420 CloseHandle( aProcessInfo
.hThread
);
422 } while ( fSuccess
&& ::desktop::ExitHelper::E_CRASH_WITH_RESTART
== dwExitCode
);
423 delete[] lpCommandLine
;
425 return fSuccess
? dwExitCode
: -1;