1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
26 #define WIN32_LEAN_AND_MEAN
28 #pragma warning(push, 1)
41 #include <systools/win32/uwinapi.h>
43 #include <rtl/string.h>
44 #include <sal/macros.h>
46 #include "../../../source/inc/exithelper.h"
47 #include "../loader.hxx"
49 #include <config_version.h>
51 #define PIPE_PREFIX TEXT("\\\\.\\pipe\\OSL_PIPE_")
52 #define PIPE_POSTFIX TEXT("_SingleOfficeIPC_")
53 #define PIPE_TERMINATION_SEQUENCE "InternalIPC::ProcessingDone"
55 BOOL WINAPI
ConvertSidToStringSid( PSID pSid
, LPTSTR
* StringSid
)
57 PSID_IDENTIFIER_AUTHORITY psia
;
58 DWORD dwSubAuthorities
;
59 DWORD dwSidRev
=SID_REVISION
;
63 // Validate the binary SID.
65 if(!IsValidSid(pSid
)) return FALSE
;
67 // Get the identifier authority value from the SID.
69 psia
= GetSidIdentifierAuthority(pSid
);
71 // Get the number of subauthorities in the SID.
73 dwSubAuthorities
= *GetSidSubAuthorityCount(pSid
);
75 // Compute the buffer length.
76 // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL
78 dwSidSize
=(15 + 12 + (12 * dwSubAuthorities
) + 1) * sizeof(TCHAR
);
80 *StringSid
= (LPTSTR
)LocalAlloc( LMEM_FIXED
, dwSidSize
);
82 // Add 'S' prefix and revision number to the string.
84 dwSidSize
=wsprintf(*StringSid
, TEXT("S-%lu-"), dwSidRev
);
86 // Add a SID identifier authority to the string.
88 if ( (psia
->Value
[0] != 0) || (psia
->Value
[1] != 0) )
90 dwSidSize
+=wsprintf(*StringSid
+ lstrlen(*StringSid
),
91 TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
92 (USHORT
)psia
->Value
[0],
93 (USHORT
)psia
->Value
[1],
94 (USHORT
)psia
->Value
[2],
95 (USHORT
)psia
->Value
[3],
96 (USHORT
)psia
->Value
[4],
97 (USHORT
)psia
->Value
[5]);
101 dwSidSize
+=wsprintf(*StringSid
+ lstrlen(*StringSid
),
103 (ULONG
)(psia
->Value
[5] ) +
104 (ULONG
)(psia
->Value
[4] << 8) +
105 (ULONG
)(psia
->Value
[3] << 16) +
106 (ULONG
)(psia
->Value
[2] << 24) );
109 // Add SID subauthorities to the string.
110 for (dwCounter
=0 ; dwCounter
< dwSubAuthorities
; dwCounter
++)
112 dwSidSize
+=wsprintf(*StringSid
+ dwSidSize
, TEXT("-%lu"),
113 *GetSidSubAuthority(pSid
, dwCounter
) );
122 static LPTSTR
*GetCommandArgs( int *pArgc
)
125 return CommandLineToArgvW( GetCommandLineW(), pArgc
);
136 bool writeArgument(HANDLE pipe
, char prefix
, WCHAR
const * argument
) {
138 int n
= WideCharToMultiByte(
139 CP_UTF8
, 0, argument
, -1, szBuffer
, sizeof (szBuffer
), NULL
, NULL
);
140 char b
[1 + 2 * ((sizeof szBuffer
) - 1)]; // hopefully does not overflow
143 for (int i
= 0; i
< n
- 1; ++i
) { // cannot underflow (n >= 0)
144 char c
= szBuffer
[i
];
164 return WriteFile(pipe
, b
, p
- b
, &w
, NULL
);
170 int WINAPI
WinMain( HINSTANCE
, HINSTANCE
, LPSTR
, int )
172 int WINAPI
_tWinMain( HINSTANCE
, HINSTANCE
, LPTSTR
, int )
175 TCHAR szTargetFileName
[MAX_PATH
] = TEXT("");
176 TCHAR szIniDirectory
[MAX_PATH
];
177 TCHAR szPerfTuneIniFile
[MAX_PATH
] = TEXT("");
178 STARTUPINFO aStartupInfo
;
180 desktop_win32::getPaths(szTargetFileName
, szIniDirectory
);
182 ZeroMemory( &aStartupInfo
, sizeof(aStartupInfo
) );
183 aStartupInfo
.cb
= sizeof(aStartupInfo
);
185 GetStartupInfo( &aStartupInfo
);
186 // Get image path with same name but with .bin extension
188 TCHAR szModuleFileName
[MAX_PATH
];
190 GetModuleFileName( NULL
, szModuleFileName
, MAX_PATH
);
191 _TCHAR
*lpLastSlash
= _tcsrchr( szModuleFileName
, '\\' );
194 size_t len
= lpLastSlash
- szModuleFileName
+ 1;
195 _tcsncpy( szPerfTuneIniFile
, szModuleFileName
, len
);
196 _tcsncpy( szPerfTuneIniFile
+ len
, _T("perftune.ini"), SAL_N_ELEMENTS(szPerfTuneIniFile
) - len
);
199 // Create process with same command line, environment and stdio handles which
200 // are directed to the created pipes
202 DWORD dwExitCode
= (DWORD
)-1;
204 BOOL fSuccess
= FALSE
;
205 LPTSTR lpCommandLine
= NULL
;
207 LPTSTR
* argv
= NULL
;
210 DWORD cwdLen
= GetCurrentDirectoryW(MAX_PATH
, cwd
);
211 if (cwdLen
>= MAX_PATH
) {
219 GetPrivateProfileString(
220 TEXT("PerformanceTuning"),
221 TEXT("FastPipeCommunication"),
224 SAL_N_ELEMENTS(szKey
),
228 if ( 0 == _tcscmp( szKey
, TEXT("1") ) )
230 HANDLE hProcessToken
;
232 if ( OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY
, &hProcessToken
) )
234 TCHAR szPipeName
[4096];
237 DWORD dwTokenLength
= 0;
240 fSuccess
= GetTokenInformation( hProcessToken
, TokenUser
, NULL
, dwTokenLength
, &dwTokenLength
);
242 PVOID pTokenInfo
= _alloca(dwTokenLength
);
243 fSuccess
= GetTokenInformation( hProcessToken
, TokenUser
, pTokenInfo
, dwTokenLength
, &dwTokenLength
);
244 CloseHandle( hProcessToken
);
246 PSID pSid
= ((PTOKEN_USER
)pTokenInfo
)->User
.Sid
;
247 LPTSTR szUserIdent
= NULL
;
248 TCHAR szSUPD
[11] = TEXT("0");
250 fSuccess
= ConvertSidToStringSid( pSid
, &szUserIdent
);
252 _tcsncpy( szPipeName
, PIPE_PREFIX
, SAL_N_ELEMENTS(szPipeName
) );
253 _tcsncat( szPipeName
, szUserIdent
, SAL_N_ELEMENTS(szPipeName
) - _tcslen(szPipeName
) - 1 );
254 _tcsncat( szPipeName
, PIPE_POSTFIX
, SAL_N_ELEMENTS(szPipeName
) - _tcslen(szPipeName
) - 1 );
255 _tcsncat( szPipeName
, _ultot( LIBO_VERSION_MAJOR
* 10000 + LIBO_VERSION_MINOR
* 100 + LIBO_VERSION_MICRO
* 1
256 , szSUPD
, 10), SAL_N_ELEMENTS(szPipeName
) - _tcslen(szPipeName
) - 1 );
258 LocalFree( szUserIdent
);
260 HANDLE hPipe
= CreateFile(
262 GENERIC_READ
|GENERIC_WRITE
,
263 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
266 FILE_ATTRIBUTE_NORMAL
,
269 if ( INVALID_HANDLE_VALUE
!= hPipe
)
271 DWORD dwBytesRead
= 0;
272 char *pBuffer
= (char *)_alloca( sizeof("InternalIPC::SendArguments") + 1);
273 fSuccess
= ReadFile( hPipe
, pBuffer
, sizeof("InternalIPC::SendArguments") + 1, &dwBytesRead
, NULL
);
276 fSuccess
= (dwBytesRead
== (sizeof("InternalIPC::SendArguments") + 1) &&
277 0 == strncmp( "InternalIPC::SendArguments", pBuffer
, dwBytesRead
- 1 ) );
281 DWORD dwBytesWritten
;
283 LPWSTR
*argv2
= CommandLineToArgvW( GetCommandLine(), &argc2
);
285 fSuccess
= WriteFile( hPipe
, RTL_CONSTASCII_STRINGPARAM("InternalIPC::Arguments"), &dwBytesWritten
, NULL
);
288 fSuccess
= writeArgument(hPipe
, '2', cwd
);
290 fSuccess
= WriteFile(
291 hPipe
, RTL_CONSTASCII_STRINGPARAM("0"),
292 &dwBytesWritten
, NULL
);
295 for ( int argn
= 1; fSuccess
&& argn
< argc2
; argn
++ )
298 argv2
[argn
], L
"-env:", std::wcslen(L
"-env:"))
301 fSuccess
= writeArgument(hPipe
, ',', argv2
[argn
]);
307 fSuccess
= WriteFile( hPipe
, "", 1, &dwBytesWritten
, NULL
);
310 DWORD dwBytesRead2
= 0;
311 char *pBuffer2
= (char *)_alloca( sizeof(PIPE_TERMINATION_SEQUENCE
) );
312 fSuccess
= ReadFile( hPipe
, pBuffer2
, sizeof(PIPE_TERMINATION_SEQUENCE
) - 1, &dwBytesRead2
, NULL
);
315 pBuffer2
[dwBytesRead2
] = 0;
316 if ( 0 != strcmp( PIPE_TERMINATION_SEQUENCE
, pBuffer2
) )
322 CloseHandle( hPipe
);
324 return fSuccess
? 0 : -1;
331 argv
= GetCommandArgs(&argc
);
332 std::size_t n
= wcslen(argv
[0]) + 2;
333 for (int i
= 1; i
< argc
; ++i
) {
334 n
+= wcslen(argv
[i
]) + 3;
336 n
+= MY_LENGTH(L
" \"-env:OOO_CWD=2") + 4 * cwdLen
+
337 MY_LENGTH(L
"\"") + 1;
338 // 4 * cwdLen: each char preceded by backslash, each trailing
340 lpCommandLine
= new WCHAR
[n
];
342 WCHAR
* p
= desktop_win32::commandLineAppend(
343 lpCommandLine
, MY_STRING(L
"\""));
344 p
= desktop_win32::commandLineAppend(p
, argv
[0]);
345 for (int i
= 1; i
< argc
; ++i
) {
346 if (bFirst
|| EXITHELPER_NORMAL_RESTART
== dwExitCode
|| wcsncmp(argv
[i
], MY_STRING(L
"-env:")) == 0) {
347 p
= desktop_win32::commandLineAppend(p
, MY_STRING(L
"\" \""));
348 p
= desktop_win32::commandLineAppend(p
, argv
[i
]);
352 p
= desktop_win32::commandLineAppend(
353 p
, MY_STRING(L
"\" \"-env:OOO_CWD="));
355 p
= desktop_win32::commandLineAppend(p
, MY_STRING(L
"0"));
357 p
= desktop_win32::commandLineAppend(p
, MY_STRING(L
"2"));
358 p
= desktop_win32::commandLineAppendEncoded(p
, cwd
);
360 desktop_win32::commandLineAppend(p
, MY_STRING(L
"\""));
363 TCHAR szParentProcessId
[64]; // This is more than large enough for a 128 bit decimal value
364 BOOL
bHeadlessMode( FALSE
);
367 // Check command line arguments for "--headless" parameter. We only
368 // set the environment variable "ATTACHED_PARENT_PROCESSID" for the headless
369 // mode as self-destruction of the soffice.bin process can lead to
370 // certain side-effects (log-off can result in data-loss, ".lock" is not deleted.
371 // See 138244 for more information.
373 LPTSTR
*argv2
= GetCommandArgs( &argc2
);
379 for ( n
= 1; n
< argc2
; n
++ )
381 if ( 0 == _tcsnicmp( argv2
[n
], _T("-headless"), 9 ) ||
382 0 == _tcsnicmp( argv2
[n
], _T("--headless"), 10 ) )
384 bHeadlessMode
= TRUE
;
390 if ( _ltot( (long)GetCurrentProcessId(),szParentProcessId
, 10 ) && bHeadlessMode
)
391 SetEnvironmentVariable( TEXT("ATTACHED_PARENT_PROCESSID"), szParentProcessId
);
393 PROCESS_INFORMATION aProcessInfo
;
395 fSuccess
= CreateProcess(
413 // On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWidth" so we have to do so
414 // as if we where processing any messages
416 dwWaitResult
= MsgWaitForMultipleObjects( 1, &aProcessInfo
.hProcess
, FALSE
, INFINITE
, QS_ALLEVENTS
);
418 if ( WAIT_OBJECT_0
+ 1 == dwWaitResult
)
422 PeekMessage( &msg
, NULL
, 0, 0, PM_REMOVE
);
424 } while ( WAIT_OBJECT_0
+ 1 == dwWaitResult
);
427 GetExitCodeProcess( aProcessInfo
.hProcess
, &dwExitCode
);
429 CloseHandle( aProcessInfo
.hProcess
);
430 CloseHandle( aProcessInfo
.hThread
);
433 && ( EXITHELPER_CRASH_WITH_RESTART
== dwExitCode
|| EXITHELPER_NORMAL_RESTART
== dwExitCode
));
434 delete[] lpCommandLine
;
436 return fSuccess
? dwExitCode
: -1;
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */