[SHELL32] CDrivesFolder: Implement the eject and disconnect menu items. CORE-13841
[reactos.git] / dll / win32 / userenv / directory.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS system libraries
22 * FILE: dll/win32/userenv/directory.c
23 * PURPOSE: User profile code
24 * PROGRAMMER: Eric Kohl
25 */
26
27 #include "precomp.h"
28
29 #define NDEBUG
30 #include <debug.h>
31
32 /* FUNCTIONS ***************************************************************/
33
34 BOOL
35 WINAPI
36 CopyProfileDirectoryA(LPCSTR lpSourcePath,
37 LPCSTR lpDestinationPath,
38 DWORD dwFlags)
39 {
40 UNICODE_STRING SrcPath;
41 UNICODE_STRING DstPath;
42 BOOL bResult;
43
44 if (!RtlCreateUnicodeStringFromAsciiz(&SrcPath,
45 (LPSTR)lpSourcePath))
46 {
47 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
48 return FALSE;
49 }
50
51 if (!RtlCreateUnicodeStringFromAsciiz(&DstPath,
52 (LPSTR)lpDestinationPath))
53 {
54 RtlFreeUnicodeString(&SrcPath);
55 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
56 return FALSE;
57 }
58
59 bResult = CopyProfileDirectoryW(SrcPath.Buffer,
60 DstPath.Buffer,
61 dwFlags);
62
63 RtlFreeUnicodeString(&DstPath);
64 RtlFreeUnicodeString(&SrcPath);
65
66 return bResult;
67 }
68
69
70 BOOL
71 WINAPI
72 CopyProfileDirectoryW(LPCWSTR lpSourcePath,
73 LPCWSTR lpDestinationPath,
74 DWORD dwFlags)
75 {
76 /* FIXME: dwFlags are ignored! */
77 return CopyDirectory(lpDestinationPath, lpSourcePath);
78 }
79
80
81 BOOL
82 CopyDirectory(LPCWSTR lpDestinationPath,
83 LPCWSTR lpSourcePath)
84 {
85 WCHAR szFileName[MAX_PATH];
86 WCHAR szFullSrcName[MAX_PATH];
87 WCHAR szFullDstName[MAX_PATH];
88 WIN32_FIND_DATAW FindFileData;
89 LPWSTR lpSrcPtr;
90 LPWSTR lpDstPtr;
91 HANDLE hFind;
92
93 DPRINT("CopyDirectory (%S, %S) called\n",
94 lpDestinationPath, lpSourcePath);
95
96 wcscpy(szFileName, lpSourcePath);
97 wcscat(szFileName, L"\\*.*");
98
99 hFind = FindFirstFileW(szFileName,
100 &FindFileData);
101 if (hFind == INVALID_HANDLE_VALUE)
102 {
103 DPRINT1("Error: %lu\n", GetLastError());
104 return FALSE;
105 }
106
107 wcscpy(szFullSrcName, lpSourcePath);
108 lpSrcPtr = AppendBackslash(szFullSrcName);
109
110 wcscpy(szFullDstName, lpDestinationPath);
111 lpDstPtr = AppendBackslash(szFullDstName);
112
113 for (;;)
114 {
115 if (wcscmp(FindFileData.cFileName, L".") &&
116 wcscmp(FindFileData.cFileName, L".."))
117 {
118 wcscpy(lpSrcPtr, FindFileData.cFileName);
119 wcscpy(lpDstPtr, FindFileData.cFileName);
120
121 if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
122 {
123 DPRINT("Create directory: %S\n", szFullDstName);
124 if (!CreateDirectoryExW(szFullSrcName, szFullDstName, NULL))
125 {
126 if (GetLastError() != ERROR_ALREADY_EXISTS)
127 {
128 DPRINT1("Error: %lu\n", GetLastError());
129
130 FindClose(hFind);
131 return FALSE;
132 }
133 }
134
135 if (!CopyDirectory(szFullDstName, szFullSrcName))
136 {
137 DPRINT1("Error: %lu\n", GetLastError());
138
139 FindClose(hFind);
140 return FALSE;
141 }
142 }
143 else
144 {
145 DPRINT("Copy file: %S -> %S\n", szFullSrcName, szFullDstName);
146 if (!CopyFileW(szFullSrcName, szFullDstName, FALSE))
147 {
148 DPRINT1("Error: %lu\n", GetLastError());
149
150 FindClose(hFind);
151 return FALSE;
152 }
153 }
154 }
155
156 if (!FindNextFileW(hFind, &FindFileData))
157 {
158 if (GetLastError() != ERROR_NO_MORE_FILES)
159 {
160 DPRINT1("Error: %lu\n", GetLastError());
161 }
162
163 break;
164 }
165 }
166
167 FindClose(hFind);
168
169 DPRINT("CopyDirectory() done\n");
170
171 return TRUE;
172 }
173
174
175 BOOL
176 CreateDirectoryPath(LPCWSTR lpPathName,
177 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
178 {
179 WCHAR szPath[MAX_PATH];
180 LPWSTR Ptr;
181 DWORD dwError;
182
183 DPRINT("CreateDirectoryPath() called\n");
184
185 if (lpPathName == NULL || *lpPathName == 0)
186 return TRUE;
187
188 if (CreateDirectoryW(lpPathName,
189 lpSecurityAttributes))
190 return TRUE;
191
192 dwError = GetLastError();
193 if (dwError == ERROR_ALREADY_EXISTS)
194 return TRUE;
195
196 wcscpy(szPath, lpPathName);
197
198 if (wcslen(szPath) > 3 && szPath[1] == ':' && szPath[2] == '\\')
199 {
200 Ptr = &szPath[3];
201 }
202 else
203 {
204 Ptr = szPath;
205 }
206
207 while (Ptr != NULL)
208 {
209 Ptr = wcschr(Ptr, L'\\');
210 if (Ptr != NULL)
211 *Ptr = 0;
212
213 DPRINT("CreateDirectory(%S)\n", szPath);
214 if (!CreateDirectoryW(szPath,
215 lpSecurityAttributes))
216 {
217 dwError = GetLastError();
218 if (dwError != ERROR_ALREADY_EXISTS)
219 return FALSE;
220 }
221
222 if (Ptr != NULL)
223 {
224 *Ptr = L'\\';
225 Ptr++;
226 }
227 }
228
229 DPRINT("CreateDirectoryPath() done\n");
230
231 return TRUE;
232 }
233
234
235 static
236 BOOL
237 RecursiveRemoveDir(LPCWSTR lpPath)
238 {
239 WCHAR szPath[MAX_PATH];
240 WIN32_FIND_DATAW FindData;
241 HANDLE hFind;
242 BOOL bResult;
243
244 wcscpy(szPath, lpPath);
245 wcscat(szPath, L"\\*.*");
246 DPRINT("Search path: '%S'\n", szPath);
247
248 hFind = FindFirstFileW(szPath,
249 &FindData);
250 if (hFind == INVALID_HANDLE_VALUE)
251 return FALSE;
252
253 bResult = TRUE;
254 while (TRUE)
255 {
256 if (wcscmp(FindData.cFileName, L".") &&
257 wcscmp(FindData.cFileName, L".."))
258 {
259 wcscpy(szPath, lpPath);
260 wcscat(szPath, L"\\");
261 wcscat(szPath, FindData.cFileName);
262 DPRINT("File name: '%S'\n", szPath);
263
264 if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
265 {
266 DPRINT("Delete directory: '%S'\n", szPath);
267
268 if (!RecursiveRemoveDir(szPath))
269 {
270 bResult = FALSE;
271 break;
272 }
273
274 if (FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
275 {
276 SetFileAttributesW(szPath,
277 FindData.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
278 }
279
280 if (!RemoveDirectoryW(szPath))
281 {
282 bResult = FALSE;
283 break;
284 }
285 }
286 else
287 {
288 DPRINT("Delete file: '%S'\n", szPath);
289
290 if (FindData.dwFileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM))
291 {
292 SetFileAttributesW(szPath,
293 FILE_ATTRIBUTE_NORMAL);
294 }
295
296 if (!DeleteFileW(szPath))
297 {
298 bResult = FALSE;
299 break;
300 }
301 }
302 }
303
304 if (!FindNextFileW(hFind, &FindData))
305 {
306 if (GetLastError() != ERROR_NO_MORE_FILES)
307 {
308 DPRINT1("Error: %lu\n", GetLastError());
309 bResult = FALSE;
310 break;
311 }
312
313 break;
314 }
315 }
316
317 FindClose(hFind);
318
319 return bResult;
320 }
321
322
323 BOOL
324 RemoveDirectoryPath(LPCWSTR lpPathName)
325 {
326 if (!RecursiveRemoveDir(lpPathName))
327 return FALSE;
328
329 DPRINT("Delete directory: '%S'\n", lpPathName);
330 return RemoveDirectoryW(lpPathName);
331 }
332
333 /* EOF */