1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
28 #pragma warning(disable:4740)
29 #endif
30 
31 #include "macros.h"
32 
33 #ifdef __cplusplus
34 #define local inline
35 #else
36 #define local static
37 #endif
38 
39 local LPCWSTR SkipBlanks( LPCWSTR lpScan )
40 {
41 	while ( ' ' == *lpScan || '\t' == *lpScan )
42 		lpScan++;
43 
44 	return lpScan;
45 }
46 
47 
48 local LPCWSTR SkipArgument( LPCWSTR lpScan )
49 {
50 	BOOL	fQuoted = FALSE;
51 	LPCWSTR	lpArgEnd = NULL;
52 
53 	do
54 	{
55 		switch ( *lpScan )
56 		{
57 		case ' ':
58 		case '\t':
59 			if ( fQuoted )
60 				lpScan++;
61 			else
62 				lpArgEnd = lpScan;
63 			break;
64 		case '\"':
65 			lpScan++;
66 			fQuoted = !fQuoted;
67 			break;
68 		case '\0':
69 			lpArgEnd = lpScan;
70 			break;
71 		default:
72 			lpScan++;
73 			break;
74 		}
75 	} while( *lpScan && !lpArgEnd );
76 
77 	return lpScan;
78 }
79 
80 
81 IMPLEMENT_THUNK( shell32, WINDOWS, LPWSTR *, WINAPI, CommandLineToArgvW, ( LPCWSTR lpCmdLineW, int *pNumArgs ) )
82 {
83 	LPWSTR	*lpArgvW = NULL;
84 
85 	if ( !lpCmdLineW || !*lpCmdLineW )
86 	{
87 		CHAR	szFileName[MAX_PATH];
88 
89 		DWORD	dwResult = GetModuleFileNameA( NULL, szFileName, MAX_PATH );
90 
91 		if ( dwResult && dwResult < MAX_PATH )
92 		{
93 			int cchNeeded = MultiByteToWideChar( CP_ACP, 0, szFileName, -1, NULL, 0 );
94 
95 			lpArgvW = (LPWSTR *)GlobalAlloc( 0, cchNeeded * sizeof(WCHAR) + sizeof(LPWSTR) );
96 
97 			if ( lpArgvW )
98 			{
99 				lpArgvW[0] = (LPWSTR)(lpArgvW + 1);
100 
101 				MultiByteToWideChar( CP_ACP, 0, szFileName, -1, lpArgvW[0], cchNeeded );
102 				*pNumArgs = 1;
103 			}
104 			else
105 				SetLastError( ERROR_OUTOFMEMORY );
106 		}
107 	}
108 	else
109 	{
110 		LPCWSTR	lpScan = lpCmdLineW;
111 		int		nTokens = 0;
112 		int		cchNeeded = 0;
113 
114 		// Count arguments and required size
115 
116 		while ( *lpScan )
117 		{
118 			lpScan = SkipBlanks( lpScan );
119 			if ( *lpScan )
120 			{
121 				LPCWSTR	lpArgEnd = SkipArgument( lpScan );
122 
123 				nTokens++;
124 				cchNeeded += lpArgEnd - lpScan + 1;
125 				lpScan = lpArgEnd;
126 			}
127 		}
128 
129 		// Allocate space for one additional NULL pointer to terminate list
130 
131 		lpArgvW = (LPWSTR *)GlobalAlloc( 0, sizeof(LPWSTR) * (nTokens + 1) + sizeof(WCHAR) * cchNeeded );
132 
133 		if ( lpArgvW )
134 		{
135 			// Collect arguments
136 
137 			LPWSTR	lpDestination = (LPWSTR)&lpArgvW[nTokens + 1];
138 
139 			lpScan = lpCmdLineW;
140 			nTokens = 0;
141 
142 			while ( *lpScan )
143 			{
144 				lpScan = SkipBlanks( lpScan );
145 				if ( *lpScan )
146 				{
147 					LPCWSTR	lpArgEnd = SkipArgument( lpScan );
148 
149 					lpArgvW[nTokens++] = lpDestination;
150 
151 					while ( lpScan < lpArgEnd )
152 					{
153 						if ( '\"' != *lpScan )
154 							*lpDestination++ = *lpScan;
155 
156 						lpScan++;
157 					}
158 					*lpDestination++ = 0;
159 				}
160 			}
161 
162 			lpArgvW[nTokens] = NULL;
163 
164 			*pNumArgs = nTokens;
165 		}
166 		else
167 			SetLastError( ERROR_OUTOFMEMORY );
168 
169 	}
170 
171 	return lpArgvW;
172 }