ReactOS 0.4.16-dev-319-g6cf4263
parsecmdline.cpp File Reference
#include "precomp.h"
#include <strsafe.h>
Include dependency graph for parsecmdline.cpp:

Go to the source code of this file.

Functions

BOOL WINAPI GUIDFromStringW (_In_ PCWSTR psz, _Out_ LPGUID pguid)
 
static BOOL _CopyAndUnquoteText (LPCWSTR strFieldSource, LPWSTR strField, size_t cchField)
 
static BOOL _FindNextArg (PCWSTR *pstrFieldSource)
 
static PCWSTR _FindFirstField (PCWSTR strFieldSource)
 
static BOOL _ReadNextArg (PCWSTR *pstrFieldSource, PWSTR strField, size_t cchField)
 
static LPITEMIDLIST _ILReadFromSharedMemory (PCWSTR strField)
 
static HRESULT _ParsePathToPidl (PWSTR strPath, LPITEMIDLIST *pidl)
 
static LPITEMIDLIST _GetDocumentsPidl ()
 
UINT_PTR WINAPI SHExplorerParseCmdLine (_Out_ PEXPLORER_CMDLINE_PARSE_RESULTS pInfo)
 

Function Documentation

◆ _CopyAndUnquoteText()

static BOOL _CopyAndUnquoteText ( LPCWSTR  strFieldSource,
LPWSTR  strField,
size_t  cchField 
)
static

Definition at line 30 of file parsecmdline.cpp.

31{
32 WCHAR cChar;
33 PWSTR tmpField = strField;
34 size_t lenField = 1;
35 BOOL inQuote = FALSE;
36
37 // Remove leading whitespace
38 cChar = *strFieldSource;
39 while (cChar == L' ' || cChar == L'\t' || cChar == L'\n' || cChar == L'\r')
40 {
41 strFieldSource = CharNextW(strFieldSource);
42 cChar = *strFieldSource;
43 }
44
45 while (cChar && cChar != L'=' && cChar != L',')
46 {
47 if (cChar == L'"')
48 {
49 // [1] is always valid read because of null-termination
50 if (inQuote && strFieldSource[1] == L'"')
51 {
52 if (lenField < cchField)
53 {
54 // Append
55 *(tmpField++) = L'"';
56 ++lenField;
57 }
58
59 // Skip second quote
60 strFieldSource++;
61 }
62 else
63 {
64 inQuote = !inQuote;
65 }
66 }
67 else
68 {
69 if (inQuote || (cChar != L'=' && cChar != L','))
70 {
71 if (lenField < cchField)
72 {
73 // Append
74 *(tmpField++) = cChar;
75 ++lenField;
76 }
77 }
78 }
79
80 strFieldSource = CharNextW(strFieldSource);
81 cChar = *strFieldSource;
82 }
83
84 // Remove trailing whitespace
85 while (tmpField > strField)
86 {
87 tmpField = CharPrevW(strField, tmpField);
88 cChar = *tmpField;
89 if (cChar != L' ' && cChar != L'\t' && cChar != L'\n' && cChar != L'\r')
90 {
91 tmpField = CharNextW(tmpField);
92 break;
93 }
94 }
95
96 // Terminate output string
97 *tmpField = 0;
98
99 return TRUE;
100}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define L(x)
Definition: ntvdm.h:50
uint16_t * PWSTR
Definition: typedefs.h:56
LPWSTR WINAPI CharPrevW(_In_ LPCWSTR, _In_ LPCWSTR)
LPWSTR WINAPI CharNextW(_In_ LPCWSTR)
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by _ReadNextArg().

◆ _FindFirstField()

static PCWSTR _FindFirstField ( PCWSTR  strFieldSource)
static

Definition at line 130 of file parsecmdline.cpp.

131{
132 //Find end of first arg, because
133 // behaviour is different if the first separator is an '='
134 BOOL inQuote = FALSE;
135 PCWSTR tmpArgs = strFieldSource;
136 WCHAR cChar = *tmpArgs;
137 while (cChar)
138 {
139 if (cChar == L'=')
140 break;
141
142 if (cChar == L',')
143 break;
144
145 if (cChar == L'\"')
146 inQuote = !inQuote;
147
148 tmpArgs = CharNextW(tmpArgs);
149 cChar = *tmpArgs;
150 }
151
152 // Skip the text before the first equal sign, if not quoted, unless the arg 0 was requested.
153 if (*tmpArgs == L'=' && !inQuote)
154 {
155 strFieldSource = ++tmpArgs;
156 TRACE("Skipped content before the first '=', remainder=%S\n", strFieldSource);
157 }
158
159 return strFieldSource;
160}
#define TRACE(s)
Definition: solgame.cpp:4
const uint16_t * PCWSTR
Definition: typedefs.h:57

Referenced by SHExplorerParseCmdLine().

◆ _FindNextArg()

static BOOL _FindNextArg ( PCWSTR pstrFieldSource)
static

Definition at line 102 of file parsecmdline.cpp.

103{
104 PCWSTR strFieldSource = *pstrFieldSource;
105 WCHAR cChar = *strFieldSource;
106 BOOL inQuote = FALSE;
107
108 while (cChar)
109 {
110 if (!inQuote && (cChar == L'=' || cChar == L','))
111 break;
112
113 if (cChar == L'"')
114 inQuote = !inQuote;
115
116 strFieldSource = CharNextW(strFieldSource);
117 cChar = *strFieldSource;
118 }
119
120 if (cChar == 0)
121 {
122 *pstrFieldSource = strFieldSource;
123 return FALSE;
124 }
125
126 *pstrFieldSource = CharNextW(strFieldSource);
127 return TRUE;
128}

Referenced by _ReadNextArg().

◆ _GetDocumentsPidl()

static LPITEMIDLIST _GetDocumentsPidl ( )
static

Definition at line 207 of file parsecmdline.cpp.

208{
210 LPITEMIDLIST pidl;
211 WCHAR guid [] = L"::{450d8fba-ad25-11d0-98a8-0800361b1103}";
212
214 return pidl;
215
216 if (FAILED(SHGetDesktopFolder(&ppshf)))
217 return NULL;
218
219 if (FAILED(ppshf->ParseDisplayName(NULL, NULL, guid, NULL, &pidl, NULL)))
220 return NULL;
221
222 return pidl;
223}
HRESULT WINAPI SHGetDesktopFolder(IShellFolder **psf)
#define NULL
Definition: types.h:112
HRESULT WINAPI SHGetSpecialFolderLocation(HWND hwndOwner, INT nFolder, LPITEMIDLIST *ppidl)
Definition: shellpath.c:3257
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
const GUID * guid
#define CSIDL_MYDOCUMENTS
Definition: shlobj.h:2185
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41

Referenced by SHExplorerParseCmdLine().

◆ _ILReadFromSharedMemory()

static LPITEMIDLIST _ILReadFromSharedMemory ( PCWSTR  strField)
static

Definition at line 170 of file parsecmdline.cpp.

171{
173
174 // Ensure it really is an IDLIST-formatted parameter
175 // Format for IDLIST params: ":pid:shared"
176 if (*strField != L':')
177 return NULL;
178
179 HANDLE hData = IntToPtr(StrToIntW(strField + 1));
180 PWSTR strSecond = StrChrW(strField + 1, L':');
181
182 if (strSecond)
183 {
184 int pid = StrToIntW(strSecond + 1);
185 void* pvShared = SHLockShared(hData, pid);
186 if (pvShared)
187 {
188 ret = ILClone((LPCITEMIDLIST) pvShared);
189 SHUnlockShared(pvShared);
190 SHFreeShared(hData, pid);
191 }
192 }
193 return ret;
194}
#define IntToPtr(i)
Definition: basetsd.h:89
INT WINAPI StrToIntW(LPCWSTR lpString)
Definition: string.c:407
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
Definition: string.c:464
PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
Definition: ordinal.c:259
BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
Definition: ordinal.c:315
BOOL WINAPI SHUnlockShared(LPVOID lpView)
Definition: ordinal.c:295
LPITEMIDLIST WINAPI ILClone(LPCITEMIDLIST pidl)
Definition: pidl.c:237
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
int ret
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837

Referenced by SHExplorerParseCmdLine().

◆ _ParsePathToPidl()

static HRESULT _ParsePathToPidl ( PWSTR  strPath,
LPITEMIDLIST pidl 
)
static

Definition at line 196 of file parsecmdline.cpp.

197{
198 CComPtr<IShellFolder> psfDesktop;
199
200 HRESULT hr = SHGetDesktopFolder(&psfDesktop);
201 if (FAILED(hr))
202 return hr;
203
204 return psfDesktop->ParseDisplayName(NULL, NULL, strPath, NULL, pidl, NULL);
205}
HRESULT hr
Definition: shlfolder.c:183

Referenced by SHExplorerParseCmdLine().

◆ _ReadNextArg()

static BOOL _ReadNextArg ( PCWSTR pstrFieldSource,
PWSTR  strField,
size_t  cchField 
)
static

Definition at line 162 of file parsecmdline.cpp.

163{
164 // Copy and unquote text
165 _CopyAndUnquoteText(*pstrFieldSource, strField, cchField);
166
167 return _FindNextArg(pstrFieldSource);
168}
static BOOL _FindNextArg(PCWSTR *pstrFieldSource)
static BOOL _CopyAndUnquoteText(LPCWSTR strFieldSource, LPWSTR strField, size_t cchField)

Referenced by SHExplorerParseCmdLine().

◆ GUIDFromStringW()

◆ SHExplorerParseCmdLine()

UINT_PTR WINAPI SHExplorerParseCmdLine ( _Out_ PEXPLORER_CMDLINE_PARSE_RESULTS  pInfo)

Definition at line 232 of file parsecmdline.cpp.

233{
234 WCHAR strField[MAX_PATH];
235 WCHAR strDir[MAX_PATH];
236
237 PCWSTR strCmdLine = GetCommandLineW();
238 PCWSTR strFieldArray = PathGetArgsW(strCmdLine);
239
240 if (!*strFieldArray)
241 {
242 pInfo->dwFlags = 9;
243 pInfo->pidlPath = _GetDocumentsPidl();
244 if (!pInfo->pidlPath)
245 {
247 PathStripToRootW(strDir);
248 pInfo->pidlPath = ILCreateFromPathW(strDir);
249 }
250 return (UINT_PTR)pInfo->pidlPath;
251 }
252
253 PCWSTR strNextArg = _FindFirstField(strFieldArray);
254
255 BOOL hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
256
257 while (TRUE)
258 {
259 // Basic flags-only params first
260 if (!StrCmpIW(strField, L"/N"))
261 {
263 TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
264 }
265 else if (!StrCmpIW(strField, L"/S"))
266 {
267 pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_S;
268 TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
269 }
270 else if (!StrCmpIW(strField, L"/E"))
271 {
272 pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_E;
273 TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
274 }
275 else if (!StrCmpIW(strField, L"/SELECT"))
276 {
277 pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_SELECT;
278 TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
279 }
280 else if (!StrCmpIW(strField, L"/NOUI"))
281 {
282 pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_NOUI;
283 TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
284 }
285 else if (!StrCmpIW(strField, L"-embedding"))
286 {
287 pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_EMBED;
288 TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
289 }
290 else if (!StrCmpIW(strField, L"/SEPARATE"))
291 {
292 pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_SEPARATE;
293 TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
294 }
295 else if (!StrCmpIW(strField, L"/INPROC"))
296 {
297 // No idea what Inproc is supposed to do, but it gets a GUID, and parses it.
298
299 TRACE("CmdLine Parser: Found %S flag\n", strField);
300
301 if (!hasNext)
302 return FALSE;
303
304 hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
305
306 if (!GUIDFromStringW(strField, &(pInfo->guidInproc)))
307 return FALSE;
308
309 pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_INPROC;
310
311 TRACE("CmdLine Parser: Parsed /INPROC flag. dwFlags=%08lx, guidInproc=%S\n", pInfo->dwFlags, strField);
312 }
313 else if (!StrCmpIW(strField, L"/ROOT"))
314 {
315 LPITEMIDLIST pidlRoot = NULL;
316
317 // The window should be rooted
318
319 TRACE("CmdLine Parser: Found %S flag\n", strField);
320
321 if (!hasNext)
322 return FALSE;
323
324 hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
325
326 // Root may be a pidl
327 if (!StrCmpIW(strField, L"/IDLIST"))
328 {
329 if (hasNext)
330 {
331 hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
332 }
333 pidlRoot = _ILReadFromSharedMemory(strField);
334 }
335 else
336 {
337 // Or just a path string
338 _ParsePathToPidl(strField, &pidlRoot);
339 }
340
341 pInfo->pidlRoot = pidlRoot;
342
343 // The root defaults to the desktop
344 if (!pidlRoot)
345 {
346 if (FAILED(SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, &(pInfo->pidlRoot))))
347 pInfo->pidlRoot = NULL;
348 }
349
350 // TODO: Create rooted PIDL from pInfo->pidlPath and pInfo->pidlRoot
351
352 TRACE("CmdLine Parser: Parsed /ROOT flag. dwFlags=%08lx, pidlRoot=%p\n", pInfo->dwFlags, pInfo->pidlRoot);
353 }
354 else
355 {
356 // Anything else is part of the target path to browse to
357 TRACE("CmdLine Parser: Found target path %S\n", strField);
358
359 // Which can be a shared-memory itemidlist
360 if (!StrCmpIW(strField, L"/IDLIST"))
361 {
362 LPITEMIDLIST pidlArg;
363
364 if (!hasNext)
365 return FALSE;
366
367 hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
368 pidlArg = _ILReadFromSharedMemory(strField);
369 if (!pidlArg)
370 return FALSE;
371
372 if (pInfo->pidlPath)
373 ILFree(pInfo->pidlPath);
374 pInfo->pidlPath = pidlArg;
375
376 TRACE("CmdLine Parser: Parsed target path. dwFlags=%08lx, pidlPath=%p\n", pInfo->dwFlags, pInfo->pidlPath);
377 }
378 else
379 {
380 // Or just a plain old string.
381
382 if (PathIsDirectoryW(strField))
383 PathAddBackslash(strField);
384
387
389 StringCchCopyW(strField, _countof(strField), szPath);
390
391 LPITEMIDLIST pidlPath = ILCreateFromPathW(strField);
392
393 pInfo->pidlPath = pidlPath;
394
395 if (pidlPath)
396 {
397 pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_IDLIST;
398 TRACE("CmdLine Parser: Parsed target path. dwFlags=%08lx, pidlPath=%p\n", pInfo->dwFlags, pInfo->pidlPath);
399 }
400 else
401 {
402 // The path could not be parsed into an ID List,
403 // so pass it on as a plain string.
404
405 PWSTR field;
406 SHStrDupW(strField, &field);
407 pInfo->strPath = field;
408 if (field)
409 {
410 pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_STRING;
411 TRACE("CmdLine Parser: Parsed target path. dwFlags=%08lx, strPath=%S\n", pInfo->dwFlags, field);
412 }
413 }
414 }
415 }
416
417 if (!hasNext)
418 break;
419 hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
420 }
421
422 return TRUE;
423}
#define SH_EXPLORER_CMDLINE_FLAG_EMBED
#define SH_EXPLORER_CMDLINE_FLAG_NEWWND
#define SH_EXPLORER_CMDLINE_FLAG_IDLIST
#define SH_EXPLORER_CMDLINE_FLAG_NOUI
#define SH_EXPLORER_CMDLINE_FLAG_INPROC
#define SH_EXPLORER_CMDLINE_FLAG_STRING
#define SH_EXPLORER_CMDLINE_FLAG_NOREUSE
#define SH_EXPLORER_CMDLINE_FLAG_SEPARATE
#define SH_EXPLORER_CMDLINE_FLAG_E
#define SH_EXPLORER_CMDLINE_FLAG_SELECT
#define SH_EXPLORER_CMDLINE_FLAG_S
#define MAX_PATH
Definition: compat.h:34
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2352
LPWSTR WINAPI GetCommandLineW(VOID)
Definition: proc.c:2019
BOOL WINAPI PathStripToRootW(LPWSTR lpszPath)
Definition: path.c:733
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1777
BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
Definition: path.c:1723
LPWSTR WINAPI PathGetArgsW(LPCWSTR lpszPath)
Definition: path.c:506
HRESULT WINAPI SHStrDupW(LPCWSTR src, LPWSTR *dest)
Definition: string.c:2018
int WINAPI StrCmpIW(LPCWSTR lpszStr, LPCWSTR lpszComp)
Definition: string.c:353
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint64EXT * result
Definition: glext.h:11304
LPCWSTR szPath
Definition: env.c:37
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
static LPITEMIDLIST _ILReadFromSharedMemory(PCWSTR strField)
static HRESULT _ParsePathToPidl(PWSTR strPath, LPITEMIDLIST *pidl)
BOOL WINAPI GUIDFromStringW(_In_ PCWSTR psz, _Out_ LPGUID pguid)
static LPITEMIDLIST _GetDocumentsPidl()
static PCWSTR _FindFirstField(PCWSTR strFieldSource)
static BOOL _ReadNextArg(PCWSTR *pstrFieldSource, PWSTR strField, size_t cchField)
void WINAPI ILFree(LPITEMIDLIST pidl)
Definition: pidl.c:1042
LPITEMIDLIST WINAPI ILCreateFromPathW(LPCWSTR path)
Definition: pidl.c:1099
#define CSIDL_DESKTOP
Definition: shlobj.h:2173
#define PathAddBackslash
Definition: shlwapi.h:809
#define _countof(array)
Definition: sndvol32.h:70
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
Definition: parser.c:44

Referenced by _tmain(), and StartWithCommandLine().