1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_desktop.hxx"
26 #define UNICODE
27 #define _UNICODE
28 
29 #define WIN32_LEAN_AND_MEAN
30 #if defined _MSC_VER
31 #pragma warning(push, 1)
32 #endif
33 #include <windows.h>
34 #include <shellapi.h>
35 #if defined _MSC_VER
36 #pragma warning(pop)
37 #endif
38 
39 #include <tchar.h>
40 
41 #include <malloc.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <systools/win32/uwinapi.h>
45 
46 #include "tools/pathutils.hxx"
47 #include "../extendloaderenvironment.hxx"
48 
49 //---------------------------------------------------------------------------
50 
GenericMain()51 static int GenericMain()
52 {
53 	TCHAR				szTargetFileName[MAX_PATH];
54 	TCHAR				szIniDirectory[MAX_PATH];
55 	STARTUPINFO			aStartupInfo;
56 
57 	desktop_win32::extendLoaderEnvironment(szTargetFileName, szIniDirectory);
58 
59 	ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) );
60 	aStartupInfo.cb = sizeof(aStartupInfo);
61 
62 	GetStartupInfo( &aStartupInfo );
63 
64 	DWORD	dwExitCode = (DWORD)-1;
65 
66 	PROCESS_INFORMATION	aProcessInfo;
67 
68 	size_t iniDirLen = wcslen(szIniDirectory);
69 	WCHAR cwd[MAX_PATH];
70 	DWORD cwdLen = GetCurrentDirectoryW(MAX_PATH, cwd);
71 	if (cwdLen >= MAX_PATH) {
72 		cwdLen = 0;
73 	}
74 	WCHAR redirect[MAX_PATH];
75 	DWORD dummy;
76 	bool hasRedirect =
77 		tools::buildPath(
78 			redirect, szIniDirectory, szIniDirectory + iniDirLen,
79 			MY_STRING(L"redirect.ini")) != NULL &&
80 		(GetBinaryType(redirect, &dummy) || // cheaper check for file existence?
81 		 GetLastError() != ERROR_FILE_NOT_FOUND);
82 	LPTSTR cl1 = GetCommandLine();
83 	WCHAR * cl2 = new WCHAR[
84 		wcslen(cl1) +
85 		(hasRedirect
86 		 ? (MY_LENGTH(L" \"-env:INIFILENAME=vnd.sun.star.pathname:") +
87 			iniDirLen + MY_LENGTH(L"redirect.ini\""))
88 		 : 0) +
89 		MY_LENGTH(L" \"-env:OOO_CWD=2") + 4 * cwdLen + MY_LENGTH(L"\"") + 1];
90 		// 4 * cwdLen: each char preceded by backslash, each trailing backslash
91 		// doubled
92 	WCHAR * p = desktop_win32::commandLineAppend(cl2, cl1);
93 	if (hasRedirect) {
94 		p = desktop_win32::commandLineAppend(
95 			p, MY_STRING(L" \"-env:INIFILENAME=vnd.sun.star.pathname:"));
96 		p = desktop_win32::commandLineAppend(p, szIniDirectory);
97 		p = desktop_win32::commandLineAppend(p, MY_STRING(L"redirect.ini\""));
98 	}
99 	p = desktop_win32::commandLineAppend(p, MY_STRING(L" \"-env:OOO_CWD="));
100 	if (cwdLen == 0) {
101 		p = desktop_win32::commandLineAppend(p, MY_STRING(L"0"));
102 	} else {
103 		p = desktop_win32::commandLineAppend(p, MY_STRING(L"2"));
104 		p = desktop_win32::commandLineAppendEncoded(p, cwd);
105 	}
106 	desktop_win32::commandLineAppend(p, MY_STRING(L"\""));
107 
108 	BOOL fSuccess = CreateProcess(
109 		szTargetFileName,
110 		cl2,
111 		NULL,
112 		NULL,
113 		TRUE,
114 		0,
115 		NULL,
116 		szIniDirectory,
117 		&aStartupInfo,
118 		&aProcessInfo );
119 
120 	delete[] cl2;
121 
122 	if ( fSuccess )
123 	{
124 		DWORD	dwWaitResult;
125 
126 		do
127 		{
128 			// On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWidth" so we have to do so
129 			// as if we were processing any messages
130 
131 			dwWaitResult = MsgWaitForMultipleObjects( 1, &aProcessInfo.hProcess, FALSE, INFINITE, QS_ALLEVENTS );
132 
133 			if ( WAIT_OBJECT_0 + 1 == dwWaitResult )
134 			{
135 				MSG	msg;
136 
137 				PeekMessage( &msg, NULL, 0, 0, PM_REMOVE );
138 			}
139 		} while ( WAIT_OBJECT_0 + 1 == dwWaitResult );
140 
141 		dwExitCode = 0;
142 		GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode );
143 
144 		CloseHandle( aProcessInfo.hProcess );
145 		CloseHandle( aProcessInfo.hThread );
146 	}
147 
148 	return dwExitCode;
149 }
150 
151 //---------------------------------------------------------------------------
152 
153 #ifdef __MINGW32__
WinMain(HINSTANCE,HINSTANCE,LPSTR,int)154 int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
155 #else
156 int WINAPI _tWinMain( HINSTANCE, HINSTANCE, LPTSTR, int )
157 #endif
158 {
159 	return GenericMain();
160 }
161 
162 //---------------------------------------------------------------------------
163 
164 #ifdef __MINGW32__
main()165 int __cdecl main()
166 #else
167 int __cdecl _tmain()
168 #endif
169 {
170 	return GenericMain();
171 }
172 
173