user: Defer all ExitWindowsEx processing to wineboot.
[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 #include <ctype.h>
24
25 #include <wine/debug.h>
26 #include "explorer_private.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(explorer);
29
30 typedef struct parametersTAG {
31     BOOL    explorer_mode;
32     WCHAR   root[MAX_PATH];
33     WCHAR   selection[MAX_PATH];
34 } parameters_struct;
35
36
37 static int CopyPathString(LPWSTR target, LPSTR source)
38 {
39     CHAR temp_buf[MAX_PATH];
40     INT i = 0;
41
42     while (isspace(*source)) source++;
43
44     if (*source == '\"')
45     {
46         source ++;
47         while (*source != '\"')
48         {
49             temp_buf[i] = *source;
50             i++;
51             source++;
52         }
53         temp_buf[i] = 0;
54         source ++;
55         i+=2;
56     }
57     else
58     {
59         while (*source && !isspace(*source))
60         {
61             temp_buf[i] = *source;
62             i++;
63             source++;
64         }
65         temp_buf[i] = 0;
66     }
67     MultiByteToWideChar(CP_ACP,0,temp_buf,-1,target,MAX_PATH);
68     return i;
69 }
70
71
72 static void CopyPathRoot(LPWSTR root, LPWSTR path)
73 {
74     LPWSTR p,p2;
75     INT i = 0;
76
77     p = path;
78     while (*p!=0)
79         p++;
80
81     while (*p!='\\' && p > path)
82         p--;
83
84     if (p == path)
85         return;
86
87     p2 = path;
88     while (p2 != p)
89     {
90         root[i] = *p2;
91         i++;
92         p2++;
93     }
94     root[i] = 0;
95 }
96
97 /*
98  * Command Line parameters are:
99  * [/n]  Opens in single-paned view for each selected items. This is default
100  * [/e,] Uses Windows Explorer View
101  * [/root,object] Specifies the root level of the view
102  * [/select,object] parent folder is opened and specified object is selected
103  */
104 static void ParseCommandLine(LPSTR commandline,parameters_struct *parameters)
105 {
106     LPSTR p;
107     LPSTR p2;
108    
109     p2 = commandline;
110     p = strchr(commandline,'/');
111     while(p)
112     {
113         p++;
114         if (strncmp(p,"n",1)==0)
115         {
116             parameters->explorer_mode = FALSE;
117             p++;
118         }
119         else if (strncmp(p,"e,",2)==0)
120         {
121             parameters->explorer_mode = TRUE;
122             p+=2;
123         }
124         else if (strncmp(p,"root,",5)==0)
125         {
126             p+=5;
127             p+=CopyPathString(parameters->root,p);
128         }
129         else if (strncmp(p,"select,",7)==0)
130         {
131             p+=7;
132             p+=CopyPathString(parameters->selection,p);
133             if (!parameters->root[0])
134                 CopyPathRoot(parameters->root,
135                         parameters->selection);
136         }
137         else if (strncmp(p,"desktop",7)==0)
138         {
139             manage_desktop( p + 7 );  /* the rest of the command line is handled by desktop mode */
140         }
141         p2 = p;
142         p = strchr(p,'/');
143     }
144     if (p2 && *p2)
145     {
146         /* left over command line is generally the path to be opened */
147         CopyPathString(parameters->root,p2);
148     }
149 }
150
151 int WINAPI WinMain(HINSTANCE hinstance,
152                    HINSTANCE previnstance,
153                    LPSTR cmdline,
154                    int cmdshow)
155 {
156     STARTUPINFOW si;
157     PROCESS_INFORMATION info;
158     parameters_struct   parameters;
159     BOOL rc;
160     static const WCHAR winefile[] = {'w','i','n','e','f','i','l','e','.','e','x','e',0};
161     static const WCHAR space[] = {' ',0};
162     LPWSTR winefile_commandline = NULL;
163     DWORD len = 0;
164
165     memset(&parameters,0,sizeof(parameters));
166     memset(&si,0,sizeof(STARTUPINFOW));
167
168     ParseCommandLine(cmdline,&parameters);
169     len = lstrlenW(winefile) +1;
170
171     if (parameters.selection[0])
172     {
173         len += lstrlenW(parameters.selection) + 2;
174         winefile_commandline = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
175
176         lstrcpyW(winefile_commandline,winefile);
177         lstrcatW(winefile_commandline,space);
178         lstrcatW(winefile_commandline,parameters.selection);
179     }
180     else if (parameters.root[0])
181     {
182         len += lstrlenW(parameters.root) + 3;
183         winefile_commandline = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
184
185         lstrcpyW(winefile_commandline,winefile);
186         lstrcatW(winefile_commandline,space);
187         lstrcatW(winefile_commandline,parameters.root);
188         if (winefile_commandline[lstrlenW(winefile_commandline)-1]!='\\')
189         {
190             static const WCHAR slash[] = {'\\',0};
191             lstrcatW(winefile_commandline,slash);
192         }
193     }
194     else
195     {
196         winefile_commandline = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
197         lstrcpyW(winefile_commandline,winefile);
198     }
199
200     rc = CreateProcessW(NULL, winefile_commandline, NULL, NULL, FALSE, 0, NULL,
201                         parameters.root, &si, &info);
202
203     HeapFree(GetProcessHeap(),0,winefile_commandline);
204
205     if (!rc)
206         return 0;
207
208     WaitForSingleObject(info.hProcess,INFINITE);
209     return 0;
210 }