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 #if defined(_MSC_VER) && (_MSC_VER >= 1400) 24 #pragma warning(disable:4740) 25 #endif 26 27 #include "macros.h" 28 29 #ifdef __cplusplus 30 #define local inline 31 #else 32 #define local static 33 #endif 34 35 local LPCWSTR SkipBlanks( LPCWSTR lpScan ) 36 { 37 while ( ' ' == *lpScan || '\t' == *lpScan ) 38 lpScan++; 39 40 return lpScan; 41 } 42 43 44 local LPCWSTR SkipArgument( LPCWSTR lpScan ) 45 { 46 BOOL fQuoted = FALSE; 47 LPCWSTR lpArgEnd = NULL; 48 49 do 50 { 51 switch ( *lpScan ) 52 { 53 case ' ': 54 case '\t': 55 if ( fQuoted ) 56 lpScan++; 57 else 58 lpArgEnd = lpScan; 59 break; 60 case '\"': 61 lpScan++; 62 fQuoted = !fQuoted; 63 break; 64 case '\0': 65 lpArgEnd = lpScan; 66 break; 67 default: 68 lpScan++; 69 break; 70 } 71 } while( *lpScan && !lpArgEnd ); 72 73 return lpScan; 74 } 75 76 77 IMPLEMENT_THUNK( shell32, WINDOWS, LPWSTR *, WINAPI, CommandLineToArgvW, ( LPCWSTR lpCmdLineW, int *pNumArgs ) ) 78 { 79 LPWSTR *lpArgvW = NULL; 80 81 if ( !lpCmdLineW || !*lpCmdLineW ) 82 { 83 CHAR szFileName[MAX_PATH]; 84 85 DWORD dwResult = GetModuleFileNameA( NULL, szFileName, MAX_PATH ); 86 87 if ( dwResult && dwResult < MAX_PATH ) 88 { 89 int cchNeeded = MultiByteToWideChar( CP_ACP, 0, szFileName, -1, NULL, 0 ); 90 91 lpArgvW = (LPWSTR *)GlobalAlloc( 0, cchNeeded * sizeof(WCHAR) + sizeof(LPWSTR) ); 92 93 if ( lpArgvW ) 94 { 95 lpArgvW[0] = (LPWSTR)(lpArgvW + 1); 96 97 MultiByteToWideChar( CP_ACP, 0, szFileName, -1, lpArgvW[0], cchNeeded ); 98 *pNumArgs = 1; 99 } 100 else 101 SetLastError( ERROR_OUTOFMEMORY ); 102 } 103 } 104 else 105 { 106 LPCWSTR lpScan = lpCmdLineW; 107 int nTokens = 0; 108 int cchNeeded = 0; 109 110 // Count arguments and required size 111 112 while ( *lpScan ) 113 { 114 lpScan = SkipBlanks( lpScan ); 115 if ( *lpScan ) 116 { 117 LPCWSTR lpArgEnd = SkipArgument( lpScan ); 118 119 nTokens++; 120 cchNeeded += lpArgEnd - lpScan + 1; 121 lpScan = lpArgEnd; 122 } 123 } 124 125 // Allocate space for one additional NULL pointer to terminate list 126 127 lpArgvW = (LPWSTR *)GlobalAlloc( 0, sizeof(LPWSTR) * (nTokens + 1) + sizeof(WCHAR) * cchNeeded ); 128 129 if ( lpArgvW ) 130 { 131 // Collect arguments 132 133 LPWSTR lpDestination = (LPWSTR)&lpArgvW[nTokens + 1]; 134 135 lpScan = lpCmdLineW; 136 nTokens = 0; 137 138 while ( *lpScan ) 139 { 140 lpScan = SkipBlanks( lpScan ); 141 if ( *lpScan ) 142 { 143 LPCWSTR lpArgEnd = SkipArgument( lpScan ); 144 145 lpArgvW[nTokens++] = lpDestination; 146 147 while ( lpScan < lpArgEnd ) 148 { 149 if ( '\"' != *lpScan ) 150 *lpDestination++ = *lpScan; 151 152 lpScan++; 153 } 154 *lpDestination++ = 0; 155 } 156 } 157 158 lpArgvW[nTokens] = NULL; 159 160 *pNumArgs = nTokens; 161 } 162 else 163 SetLastError( ERROR_OUTOFMEMORY ); 164 165 } 166 167 return lpArgvW; 168 }