msi: Add tests for removing registry values.
[wine] / programs / explorer / explorer.c
1 /*
2  * explorer.exe
3  *
4  * Copyright 2004 CodeWeavers, Mike Hearn
5  * Copyright 2005,2006 CodeWeavers, Aric Stewart
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <windows.h>
23
24 #include "wine/unicode.h"
25 #include "explorer_private.h"
26
27 typedef struct parametersTAG {
28     BOOL    explorer_mode;
29     WCHAR   root[MAX_PATH];
30     WCHAR   selection[MAX_PATH];
31 } parameters_struct;
32
33
34 static int CopyPathString(LPWSTR target, LPWSTR source)
35 {
36     INT i = 0;
37
38     while (isspaceW(*source)) source++;
39
40     if (*source == '\"')
41     {
42         source ++;
43         while (*source != '\"') target[i++] = *source++;
44         target[i] = 0;
45         source ++;
46         i+=2;
47     }
48     else
49     {
50         while (*source && !isspaceW(*source)) target[i++] = *source++;
51         target[i] = 0;
52     }
53     return i;
54 }
55
56
57 static void CopyPathRoot(LPWSTR root, LPWSTR path)
58 {
59     LPWSTR p,p2;
60     INT i = 0;
61
62     p = path;
63     while (*p!=0)
64         p++;
65
66     while (*p!='\\' && p > path)
67         p--;
68
69     if (p == path)
70         return;
71
72     p2 = path;
73     while (p2 != p)
74     {
75         root[i] = *p2;
76         i++;
77         p2++;
78     }
79     root[i] = 0;
80 }
81
82 /*
83  * Command Line parameters are:
84  * [/n]  Opens in single-paned view for each selected items. This is default
85  * [/e,] Uses Windows Explorer View
86  * [/root,object] Specifies the root level of the view
87  * [/select,object] parent folder is opened and specified object is selected
88  */
89 static void ParseCommandLine(LPWSTR commandline,parameters_struct *parameters)
90 {
91     static const WCHAR arg_n[] = {'/','n'};
92     static const WCHAR arg_e[] = {'/','e',','};
93     static const WCHAR arg_root[] = {'/','r','o','o','t',','};
94     static const WCHAR arg_select[] = {'/','s','e','l','e','c','t',','};
95     static const WCHAR arg_desktop[] = {'/','d','e','s','k','t','o','p'};
96
97     LPWSTR p, p2;
98
99     p2 = commandline;
100     p = strchrW(commandline,'/');
101     while(p)
102     {
103         if (strncmpW(p, arg_n, sizeof(arg_n)/sizeof(WCHAR))==0)
104         {
105             parameters->explorer_mode = FALSE;
106             p += sizeof(arg_n)/sizeof(WCHAR);
107         }
108         else if (strncmpW(p, arg_e, sizeof(arg_e)/sizeof(WCHAR))==0)
109         {
110             parameters->explorer_mode = TRUE;
111             p += sizeof(arg_e)/sizeof(WCHAR);
112         }
113         else if (strncmpW(p, arg_root, sizeof(arg_root)/sizeof(WCHAR))==0)
114         {
115             p += sizeof(arg_root)/sizeof(WCHAR);
116             p+=CopyPathString(parameters->root,p);
117         }
118         else if (strncmpW(p, arg_select, sizeof(arg_select)/sizeof(WCHAR))==0)
119         {
120             p += sizeof(arg_select)/sizeof(WCHAR);
121             p+=CopyPathString(parameters->selection,p);
122             if (!parameters->root[0])
123                 CopyPathRoot(parameters->root,
124                         parameters->selection);
125         }
126         else if (strncmpW(p, arg_desktop, sizeof(arg_desktop)/sizeof(WCHAR))==0)
127         {
128             p += sizeof(arg_desktop)/sizeof(WCHAR);
129             manage_desktop( p );  /* the rest of the command line is handled by desktop mode */
130         }
131         else p++;
132
133         p2 = p;
134         p = strchrW(p,'/');
135     }
136     if (p2 && *p2)
137     {
138         /* left over command line is generally the path to be opened */
139         CopyPathString(parameters->root,p2);
140     }
141 }
142
143 int WINAPI wWinMain(HINSTANCE hinstance,
144                     HINSTANCE previnstance,
145                     LPWSTR cmdline,
146                     int cmdshow)
147 {
148     STARTUPINFOW si;
149     PROCESS_INFORMATION info;
150     parameters_struct   parameters;
151     BOOL rc;
152     static const WCHAR winefile[] = {'\\','w','i','n','e','f','i','l','e','.','e','x','e',0};
153     static const WCHAR space[] = {' ',0};
154     WCHAR app[MAX_PATH];
155     LPWSTR winefile_commandline = NULL;
156     DWORD len = 0;
157
158     memset(&parameters,0,sizeof(parameters));
159     memset(&si,0,sizeof(STARTUPINFOW));
160
161     ParseCommandLine(cmdline,&parameters);
162     len = GetSystemDirectoryW( NULL, 0 ) + sizeof(winefile)/sizeof(WCHAR);
163
164     if (parameters.selection[0]) len += lstrlenW(parameters.selection) + 2;
165     else if (parameters.root[0]) len += lstrlenW(parameters.root) + 3;
166
167     winefile_commandline = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
168     GetSystemDirectoryW( app, MAX_PATH - sizeof(winefile)/sizeof(WCHAR) );
169     strcatW( app, winefile );
170     strcpyW( winefile_commandline, app );
171
172     if (parameters.selection[0])
173     {
174         lstrcatW(winefile_commandline,space);
175         lstrcatW(winefile_commandline,parameters.selection);
176     }
177     else if (parameters.root[0])
178     {
179         lstrcatW(winefile_commandline,space);
180         lstrcatW(winefile_commandline,parameters.root);
181         if (winefile_commandline[lstrlenW(winefile_commandline)-1]!='\\')
182         {
183             static const WCHAR slash[] = {'\\',0};
184             lstrcatW(winefile_commandline,slash);
185         }
186     }
187
188     rc = CreateProcessW(app, winefile_commandline, NULL, NULL, FALSE, 0, NULL,
189                         parameters.root[0] ? parameters.root:NULL, &si, &info);
190
191     HeapFree(GetProcessHeap(),0,winefile_commandline);
192
193     if (!rc)
194         return 0;
195
196     CloseHandle(info.hThread);
197     WaitForSingleObject(info.hProcess,INFINITE);
198     CloseHandle(info.hProcess);
199     return 0;
200 }