source: trunk/src/shell32/shlfileop.c@ 9304

Last change on this file since 9304 was 9244, checked in by sandervl, 23 years ago

DT: resync with Wine

File size: 23.7 KB
Line 
1/*
2 * SHFileOperation
3 * Copyright 2000 Juergen Schmied
4 * Copyright 2002 Andriy Palamarchuk
5 * Copyright 2002 Dietrich Teickner (from Odin)
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#ifdef __WIN32OS2__
22#define ICOM_CINTERFACE 1
23#include <odin.h>
24#endif
25#include <string.h>
26#include "debugtools.h"
27#include "shellapi.h"
28#include "shlwapi.h"
29
30#include "shlobj.h"
31#include "shresdef.h"
32#include "shell32_main.h"
33#include "undocshell.h"
34#include "shlwapi.h"
35
36DEFAULT_DEBUG_CHANNEL(shell);
37
38
39#ifdef __WIN32OS2__
40BOOL SHELL_ConfirmDialog (int nKindOfDialog, LPCSTR szDir)
41{
42 char szCaption[255], szText[255], szBuffer[MAX_PATH + 256];
43 UINT caption_resource_id, text_resource_id;
44
45 switch(nKindOfDialog) {
46
47 case ASK_DELETE_FILE:
48 caption_resource_id = IDS_DELETEITEM_CAPTION;
49 text_resource_id = IDS_DELETEITEM_TEXT;
50 break;
51 case ASK_DELETE_FOLDER:
52 caption_resource_id = IDS_DELETEFOLDER_CAPTION;
53 text_resource_id = IDS_DELETEITEM_TEXT;
54 break;
55 case ASK_DELETE_MULTIPLE_ITEM:
56 caption_resource_id = IDS_DELETEITEM_CAPTION;
57 text_resource_id = IDS_DELETEMULTIPLE_TEXT;
58 break;
59 case ASK_OVERWRITE_FILE:
60 caption_resource_id = IDS_OVERWRITEFILE_CAPTION;
61 text_resource_id = IDS_OVERWRITEFILE_TEXT;
62 break;
63 default:
64 FIXME(__FUNCTION__" Unhandled nKindOfDialog %d stub\n", nKindOfDialog);
65 return FALSE;
66 }
67
68 LoadStringA(shell32_hInstance, caption_resource_id, szCaption, sizeof(szCaption));
69 LoadStringA(shell32_hInstance, text_resource_id, szText, sizeof(szText));
70#else
71BOOL SHELL_WarnItemDelete (int nKindOfDialog, LPCSTR szDir)
72{
73 char szCaption[255], szText[255], szBuffer[MAX_PATH + 256];
74
75 if(nKindOfDialog == ASK_DELETE_FILE)
76 {
77 LoadStringA(shell32_hInstance, IDS_DELETEITEM_TEXT, szText,
78 sizeof(szText));
79 LoadStringA(shell32_hInstance, IDS_DELETEITEM_CAPTION,
80 szCaption, sizeof(szCaption));
81 }
82 else if(nKindOfDialog == ASK_DELETE_FOLDER)
83 {
84 LoadStringA(shell32_hInstance, IDS_DELETEITEM_TEXT, szText,
85 sizeof(szText));
86 LoadStringA(shell32_hInstance, IDS_DELETEFOLDER_CAPTION,
87 szCaption, sizeof(szCaption));
88 }
89 else if(nKindOfDialog == ASK_DELETE_MULTIPLE_ITEM)
90 {
91 LoadStringA(shell32_hInstance, IDS_DELETEMULTIPLE_TEXT, szText,
92 sizeof(szText));
93 LoadStringA(shell32_hInstance, IDS_DELETEITEM_CAPTION,
94 szCaption, sizeof(szCaption));
95 }
96 else {
97 FIXME("Called without a valid nKindOfDialog specified!");
98 LoadStringA(shell32_hInstance, IDS_DELETEITEM_TEXT, szText,
99 sizeof(szText));
100 LoadStringA(shell32_hInstance, IDS_DELETEITEM_CAPTION,
101 szCaption, sizeof(szCaption));
102 }
103#endif
104 FormatMessageA(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
105 szText, 0, 0, szBuffer, sizeof(szBuffer), (va_list*)&szDir);
106
107 return (IDOK == MessageBoxA(GetActiveWindow(), szBuffer, szCaption, MB_OKCANCEL | MB_ICONEXCLAMATION));
108}
109
110/**************************************************************************
111 * SHELL_DeleteDirectoryA()
112 *
113 * like rm -r
114 */
115
116BOOL SHELL_DeleteDirectoryA(LPCSTR pszDir, BOOL bShowUI)
117{
118 BOOL ret = FALSE;
119 HANDLE hFind;
120 WIN32_FIND_DATAA wfd;
121 char szTemp[MAX_PATH];
122
123 strcpy(szTemp, pszDir);
124 PathAddBackslashA(szTemp);
125 strcat(szTemp, "*.*");
126
127 if (bShowUI && !SHELL_WarnItemDelete(ASK_DELETE_FOLDER, pszDir))
128 return FALSE;
129
130 if(INVALID_HANDLE_VALUE != (hFind = FindFirstFileA(szTemp, &wfd)))
131 {
132 do
133 {
134 if(strcasecmp(wfd.cFileName, ".") && strcasecmp(wfd.cFileName, ".."))
135 {
136 strcpy(szTemp, pszDir);
137 PathAddBackslashA(szTemp);
138 strcat(szTemp, wfd.cFileName);
139
140 if(FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
141 SHELL_DeleteDirectoryA(szTemp, FALSE);
142 else
143 DeleteFileA(szTemp);
144 }
145 } while(FindNextFileA(hFind, &wfd));
146
147 FindClose(hFind);
148 ret = RemoveDirectoryA(pszDir);
149 }
150
151 return ret;
152}
153
154/**************************************************************************
155 * SHELL_DeleteFileA()
156 */
157
158BOOL SHELL_DeleteFileA(LPCSTR pszFile, BOOL bShowUI)
159{
160 if (bShowUI && !SHELL_WarnItemDelete(ASK_DELETE_FILE, pszFile))
161 return FALSE;
162
163 return DeleteFileA(pszFile);
164}
165
166/*************************************************************************
167 * SHCreateDirectory [SHELL32.165]
168 *
169 * NOTES
170 * exported by ordinal
171 * not sure about LPSECURITY_ATTRIBUTES
172 */
173DWORD WINAPI SHCreateDirectory(LPSECURITY_ATTRIBUTES sec,LPCSTR path)
174{
175 DWORD ret;
176 TRACE("(%p,%s)\n",sec,path);
177 if ((ret = CreateDirectoryA(path,sec)))
178 {
179 SHChangeNotifyA(SHCNE_MKDIR, SHCNF_PATHA, path, NULL);
180 }
181 return ret;
182}
183
184/************************************************************************
185 * Win32DeleteFile [SHELL32.164]
186 *
187 * Deletes a file. Also triggers a change notify if one exists.
188 *
189 * FIXME:
190 * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be
191 * ANSI. Is this Unicode on NT?
192 *
193 */
194
195BOOL WINAPI Win32DeleteFile(LPSTR fName)
196{
197 TRACE("%p(%s)\n", fName, fName);
198
199 DeleteFileA(fName);
200 SHChangeNotifyA(SHCNE_DELETE, SHCNF_PATHA, fName, NULL);
201 return TRUE;
202}
203
204/*************************************************************************
205 * SHFileOperationA [SHELL32.243]
206 *
207 * NOTES
208 * exported by name
209 */
210DWORD WINAPI SHFileOperationA (LPSHFILEOPSTRUCTA lpFileOp)
211{
212 LPSTR pFrom = (LPSTR)lpFileOp->pFrom;
213 LPSTR pTo = (LPSTR)lpFileOp->pTo;
214 LPSTR pTempTo;
215#ifdef __WIN32OS2__
216 DWORD FromAttr;
217 DWORD ToAttr;
218 LPSTR pTempFrom = NULL;
219 LPSTR pFromFile;
220 LPSTR pToFile;
221
222 FILEOP_FLAGS OFl = ((FILEOP_FLAGS)lpFileOp->fFlags & 0x7ff);
223 BOOL Multi = TRUE;
224 BOOL withFileName = TRUE;
225 BOOL not_overwrite;
226 BOOL ToSingle;
227 BOOL BothDir;
228 BOOL ToWithoutBackSlash;
229 long lenFrom = -1;
230 long lenTo = -1;
231 long lenTempFrom;
232 long lenTempTo;
233 long retCode = 0x75;
234 long TempretCode = 0;
235 long where = 0;
236 SHFILEOPSTRUCTA nlpFileOp = *(lpFileOp);
237 long level= nlpFileOp.wFunc>>4;
238 HANDLE hFind;
239 WIN32_FIND_DATAA wfd;
240
241/* default no error
242*/
243 lpFileOp->fAnyOperationsAborted=FALSE;
244 nlpFileOp.fAnyOperationsAborted=FALSE;
245 level++;
246 nlpFileOp.wFunc = (level<<4) + (lpFileOp->wFunc & 15);
247 if (level == 1)
248#endif
249 TRACE("flags (0x%04x) : %s%s%s%s%s%s%s%s%s%s%s%s \n", lpFileOp->fFlags,
250 lpFileOp->fFlags & FOF_MULTIDESTFILES ? "FOF_MULTIDESTFILES " : "",
251 lpFileOp->fFlags & FOF_CONFIRMMOUSE ? "FOF_CONFIRMMOUSE " : "",
252 lpFileOp->fFlags & FOF_SILENT ? "FOF_SILENT " : "",
253 lpFileOp->fFlags & FOF_RENAMEONCOLLISION ? "FOF_RENAMEONCOLLISION " : "",
254 lpFileOp->fFlags & FOF_NOCONFIRMATION ? "FOF_NOCONFIRMATION " : "",
255 lpFileOp->fFlags & FOF_WANTMAPPINGHANDLE ? "FOF_WANTMAPPINGHANDLE " : "",
256 lpFileOp->fFlags & FOF_ALLOWUNDO ? "FOF_ALLOWUNDO " : "",
257 lpFileOp->fFlags & FOF_FILESONLY ? "FOF_FILESONLY " : "",
258 lpFileOp->fFlags & FOF_SIMPLEPROGRESS ? "FOF_SIMPLEPROGRESS " : "",
259 lpFileOp->fFlags & FOF_NOCONFIRMMKDIR ? "FOF_NOCONFIRMMKDIR " : "",
260 lpFileOp->fFlags & FOF_NOERRORUI ? "FOF_NOERRORUI " : "",
261 lpFileOp->fFlags & 0xf800 ? "MORE-UNKNOWN-Flags" : "");
262#ifdef __WIN32OS2__
263 switch(lpFileOp->wFunc & 15) {
264#else
265 switch(lpFileOp->wFunc) {
266#endif
267 case FO_COPY:
268 /* establish when pTo is interpreted as the name of the destination file
269 * or the directory where the Fromfile should be copied to.
270 * This depends on:
271 * (1) pTo points to the name of an existing directory;
272 * (2) the flag FOF_MULTIDESTFILES is present;
273 * (3) whether pFrom point to multiple filenames.
274 *
275 * Some experiments:
276 *
277 * destisdir 1 1 1 1 0 0 0 0
278 * FOF_MULTIDESTFILES 1 1 0 0 1 1 0 0
279 * multiple from filenames 1 0 1 0 1 0 1 0
280 * ---------------
281 * copy files to dir 1 0 1 1 0 0 1 0
282 * create dir 0 0 0 0 0 0 1 0
283 */
284#ifdef __WIN32OS2__
285 pTempFrom = HeapAlloc(GetProcessHeap(), 0, 3 * MAX_PATH+6);
286 pTempTo = &pTempFrom[MAX_PATH+4];
287/*
288 * FOF_MULTIDESTFILES, FOF_NOCONFIRMATION, FOF_FILESONLY are implemented
289 * FOF_CONFIRMMOUSE, FOF_SILENT, FOF_NOCONFIRMMKDIR, FOF_SIMPLEPROGRESS are not implemented and ignored
290 * FOF_RENAMEONCOLLISION are implemented partially and breaks if file exist
291 * FOF_ALLOWUNDO, FOF_WANTMAPPINGHANDLE are not implemented and breaks
292 * if any other flag set, an error occurs
293 */
294 TRACE(__FUNCTION__" FO_COPY level=%d lpFileOp->fFlags=0x%x\n",level ,lpFileOp->fFlags);
295// OFl = (OFl & (-1 - (FOF_MULTIDESTFILES | FOF_FILESONLY)));
296// OFl = (OFl ^ (FOF_SILENT | FOF_NOCONFIRMATION | FOF_SIMPLEPROGRESS | FOF_NOCONFIRMMKDIR));
297 OFl = (OFl & ( ~ (FOF_MULTIDESTFILES | FOF_NOCONFIRMATION | FOF_FILESONLY))); // implemented
298 OFl = (OFl ^ (FOF_SILENT | FOF_NOCONFIRMMKDIR)); // ignored, if one
299 OFl = (OFl & ( ~ FOF_SIMPLEPROGRESS)); // ignored, only with FOF_SILENT
300 if (OFl) {
301 if (OFl & ( ~ (FOF_CONFIRMMOUSE | FOF_SILENT | FOF_RENAMEONCOLLISION | FOF_NOCONFIRMMKDIR))) {
302 TRACE(__FUNCTION__" FO_COPY level=%d lpFileOp->fFlags=0x%x not implemented, Aborted=TRUE, stub\n", level, OFl);
303 nlpFileOp.fAnyOperationsAborted=TRUE;
304 } else {
305 TRACE(__FUNCTION__" FO_COPY level=%d lpFileOp->fFlags=0x%x not full implemented ,stub\n", level, OFl);
306 } /* endif */
307 } /* endif */
308
309 not_overwrite = (!(lpFileOp->fFlags & FOF_NOCONFIRMATION) || (lpFileOp->fFlags & FOF_RENAMEONCOLLISION));
310
311// fix for more then one source for one target
312 pToFile = pTempTo;
313
314// need break at error before change sourcepointer
315 while(!nlpFileOp.fAnyOperationsAborted && (pFrom+=lenFrom+1)[0]) {
316
317 if (!withFileName && Multi && (pTo[lenTo+1]=='\0')) {
318// Win Bug ?
319 Multi = FALSE;
320 } /* endif */
321
322 if (Multi) pTo += lenTo + 1;
323 if(!pTo[0]) {
324 nlpFileOp.fAnyOperationsAborted=TRUE;
325 where = 213;
326 break;
327 }
328
329 TRACE(__FUNCTION__" FO_COPY level=%d From='%s' To='%s'\n", level, pFrom, pTo);
330
331// fix for more then one source for one target
332 pToFile[0] = '\0';
333 nlpFileOp.pTo = pTo;
334
335 lenFrom=strlen(pFrom);
336 strcpy(pTempFrom,pFrom);
337 FromAttr = GetFileAttributesA(pTempFrom);
338
339 if (Multi) {
340 lenTo = strlen(pTo);
341// single targetdir !Multi
342 Multi = (Multi && (lpFileOp->fFlags & FOF_MULTIDESTFILES));
343// multi target, each one for one source. ? last target + more than one source (all source files an one dir as target)
344
345 ToSingle = ((pTo[lenTo+1]=='\0') || !Multi);
346
347 strcpy(pTempTo,pTo);
348 PathRemoveBackslashA(pTempTo);
349 ToWithoutBackSlash = (strlen(pTempTo)==lenTo);
350 ToAttr = GetFileAttributesA(pTempTo);
351
352 BothDir = (Multi &&
353 ToWithoutBackSlash &&
354 (-1 != (FromAttr | ToAttr)) &&
355 (ToAttr & FromAttr & FILE_ATTRIBUTE_DIRECTORY));
356
357 withFileName = (!BothDir &&
358 (ToWithoutBackSlash || !ToSingle) &&
359 (ToAttr == -1 || !(ToAttr & FILE_ATTRIBUTE_DIRECTORY)));
360
361 if (withFileName) {
362// Target must not be an directory
363 PathRemoveFileSpecA(pTempTo);
364 ToAttr = GetFileAttributesA(pTempTo);
365 }
366 if ((ToAttr == -1) ||
367 !(ToAttr & FILE_ATTRIBUTE_DIRECTORY) ||
368 (!withFileName && !ToSingle) ) {
369 nlpFileOp.fAnyOperationsAborted=TRUE;
370 where = 201;
371 break;
372 }
373 lenTempTo = strlen(pTempTo);
374 withFileName = (((lenTempTo + 1) < lenTo) || (PathIsRootA(pTo) && lenTempTo < lenTo));
375 PathAddBackslashA(pTempTo);
376 }
377
378 if (FromAttr == -1 || BothDir) {
379// is Source an existing directory\*.* ?
380 if (FromAttr == -1) {
381 PathRemoveFileSpecA(pTempFrom);
382 FromAttr = GetFileAttributesA(pTempFrom);
383 }
384
385 PathAddBackslashA(pTempFrom);
386 lenTempFrom = strlen(pTempFrom);
387 pFromFile=&pTempFrom[lenTempFrom];
388
389 if (FromAttr == -1 ||
390 ((lenTempFrom==lenFrom) && !PathIsRootA(pFrom)) ||
391 !(FromAttr & FILE_ATTRIBUTE_DIRECTORY) ||
392 !((0==strcmp(&pFrom[lenTempFrom],"*.*")) || BothDir)) {
393 retCode=0x402;
394 nlpFileOp.fAnyOperationsAborted=TRUE;
395 where = 202;
396 break;
397 }
398
399 strcpy(pFromFile, "*.*");
400 hFind = FindFirstFileA(pTempFrom, &wfd);
401 if (INVALID_HANDLE_VALUE == hFind) {
402 nlpFileOp.fAnyOperationsAborted=TRUE;
403 retCode=0x79;
404 where = 203;
405 break;
406 }
407
408 nlpFileOp.pFrom = pTempFrom;
409// single copy never with FOF_MULTIDESTFILES, I can use lpFileOp->pTo as nlpFileOp.pTo,
410// I need no different targetarea for the name
411 TRACE(__FUNCTION__" FO_COPY level=%d Copy between Subdir %s -> %s'\n",level ,nlpFileOp.pFrom, nlpFileOp.pTo);
412 nlpFileOp.fFlags = (nlpFileOp.fFlags & (-1 - (FOF_MULTIDESTFILES)));
413
414 do {
415 TRACE(__FUNCTION__" FO_COPY level=%d find '%s'\n",level ,wfd.cFileName);
416 if (0==strcmp(wfd.cFileName,".")) continue;
417 if (0==strcmp(wfd.cFileName,"..")) continue;
418 if ((nlpFileOp.fFlags & FOF_FILESONLY) && (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)) {
419 continue;
420 } /* endif */
421
422 strcpy(pFromFile,wfd.cFileName);
423 pTempFrom[strlen(pTempFrom)+1]='\0';
424
425 TempretCode = SHFileOperationA (&nlpFileOp);
426
427 if (nlpFileOp.fAnyOperationsAborted) {where = 204;break;}
428
429 } while(FindNextFileA(hFind, &wfd));
430
431 FindClose(hFind);
432 if (nlpFileOp.fAnyOperationsAborted) {where = 205;break;}
433 continue;
434 }
435
436 lenTempTo = strlen(pTempTo);
437 pToFile = &pTempTo[lenTempTo];
438// Check Source
439 strcpy(pToFile,pTempFrom);
440 PathRemoveBackslashA(pToFile);
441 if (strlen(pToFile)<lenFrom) {
442 nlpFileOp.fAnyOperationsAborted=TRUE;
443 retCode=0x402;
444 where = 206;
445 break;
446 } /* endif */
447
448// target name in target or from source
449 pFromFile = NULL;
450 if (withFileName) {
451 if ((pFrom[lenFrom+1]=='\0') || (Multi && !(pTo[lenTo+1]=='\0'))) {
452 pFromFile = pTo;
453 } /* endif */
454 } else {
455// Multi Target
456 if (!Multi || !(pFrom[lenFrom+1]=='\0') ||
457// only target+\, target without \ has 0x402
458 (Multi && (FromAttr & ToAttr & FILE_ATTRIBUTE_DIRECTORY))) {
459 pFromFile = pTempFrom;
460 }
461 } /* endif */
462
463 if (!pFromFile) {
464 nlpFileOp.fAnyOperationsAborted=TRUE;
465 where = 207;
466 break;
467 } /* endif */
468
469// move isolated target filename
470 strcpy(pToFile,pFromFile);
471 PathRemoveFileSpecA(pToFile);
472 PathAddBackslashA(pToFile);
473
474 strcpy(pToFile,&pFromFile[strlen(pToFile)]);
475 ToAttr = GetFileAttributesA(pTempTo);
476
477 if (FromAttr == -1) {
478 TRACE(__FUNCTION__" FO_COPY level=%d with Source %s not implementiert ,stub\n",level ,pTempFrom);
479 nlpFileOp.fAnyOperationsAborted=TRUE;
480 where = 208;
481 break;
482 }
483 if (FromAttr & FILE_ATTRIBUTE_DIRECTORY) {
484 if (ToAttr == -1) {
485// Try to create an new Directory and enter in it
486 TRACE(__FUNCTION__" FO_COPY level=%d Creating Directory '%s'\n",level , pTempTo);
487 SHCreateDirectory(NULL,pTempTo);
488 ToAttr = GetFileAttributesA(pTempTo);
489 if (ToAttr == -1) {
490 nlpFileOp.fAnyOperationsAborted=TRUE;
491 retCode=0x10003;
492 where = 209;
493 break;
494 }
495
496 lenTempTo = strlen(pTempTo);
497
498 PathAddBackslashA(pTempFrom);
499 strcat(pTempFrom, "*.*");
500 pTempFrom[strlen(pTempFrom)+1]='\0';
501 nlpFileOp.pFrom = pTempFrom;
502
503 pTempTo[lenTempTo+1]='\0';
504 nlpFileOp.pTo = pTempTo;
505
506 TRACE(__FUNCTION__" FO_COPY level=%d Entering Directory '%s'\n",level , nlpFileOp.pTo);
507 TempretCode = SHFileOperationA (&nlpFileOp);
508
509 if (nlpFileOp.fAnyOperationsAborted) {break;}
510 continue;
511
512 } else {
513 TRACE(__FUNCTION__" FO_COPY level=%d unexpected with %s -> %s ? ,stub\n",level ,pTempFrom,pTo);
514 nlpFileOp.fAnyOperationsAborted=TRUE;
515 where = 210;
516 retCode=0x77;
517 break;
518
519 }
520
521 }
522
523 if (!(ToAttr == -1) && (ToAttr & FILE_ATTRIBUTE_DIRECTORY)) {
524 nlpFileOp.fAnyOperationsAborted=TRUE;
525 where = 211;
526 break;
527 }
528 if (0==strcmp(pTempFrom, pTempTo)) {
529 nlpFileOp.fAnyOperationsAborted=TRUE;
530 retCode = 0x71;
531 where = 212;
532 break;
533 }
534// first try to copy
535 if (CopyFileA(pTempFrom, pTempTo, not_overwrite)) continue;
536
537 if ((not_overwrite) && !(lpFileOp->fFlags & FOF_RENAMEONCOLLISION)) {
538 if (SHELL_ConfirmDialog (ASK_OVERWRITE_FILE, pTempTo))
539// second try to copy after confirm
540 if (CopyFileA(pTempFrom, pTempTo, FALSE)) continue;
541 } /* endif */
542
543 nlpFileOp.fAnyOperationsAborted=TRUE;
544 where = 215;
545 }
546 break;
547#else
548 while(1) {
549 if(!pFrom[0]) break;
550 if(!pTo[0]) break;
551 TRACE(" From='%s' To='%s'\n", pFrom, pTo);
552
553 pTempTo = HeapAlloc(GetProcessHeap(), 0, strlen(pTo)+1);
554 if (pTempTo)
555 {
556 strcpy( pTempTo, pTo );
557 PathRemoveFileSpecA(pTempTo);
558 TRACE(" Creating Directory '%s'\n", pTempTo);
559 SHCreateDirectory(NULL,pTempTo);
560 HeapFree(GetProcessHeap(), 0, pTempTo);
561 }
562 CopyFileA(pFrom, pTo, FALSE);
563
564 pFrom += strlen(pFrom) + 1;
565 pTo += strlen(pTo) + 1;
566 }
567 TRACE("Setting AnyOpsAborted=FALSE\n");
568 lpFileOp->fAnyOperationsAborted=FALSE;
569 return 0;
570#endif
571
572 case FO_DELETE:
573#ifdef __WIN32OS2__
574 TRACE(__FUNCTION__" FO_DELETE level=%d\n",level);
575// need break at error before change sourcepointer
576 while(!nlpFileOp.fAnyOperationsAborted && (pFrom+=lenFrom+1)[0]) {
577 lenFrom=strlen(pFrom);
578 FromAttr = GetFileAttributesA(pFrom);
579 if (!(FromAttr & FILE_ATTRIBUTE_DIRECTORY)) {
580 TRACE(__FUNCTION__" FO_DELETE level=%d File='%s'\n",level , pFrom);
581 if (DeleteFileA(pFrom)) continue;
582 nlpFileOp.fAnyOperationsAborted=TRUE;
583// retCode = 0x71;
584 where = 301;
585 break;
586 }
587 if (!(pTempFrom)) pTempFrom = HeapAlloc(GetProcessHeap(), 0, MAX_PATH+2);
588 strcpy(pTempFrom,pFrom);
589 PathRemoveBackslashA(pTempFrom);
590 FromAttr = GetFileAttributesA(pTempFrom);
591 if (!(FromAttr & FILE_ATTRIBUTE_DIRECTORY) ) {
592 nlpFileOp.fAnyOperationsAborted=TRUE;
593// retCode = 0x71;
594 where = 302;
595 break;
596 }
597// is Source an existing directory\*.* ?
598 if (FromAttr == -1) {
599 PathRemoveFileSpecA(pTempFrom);
600 FromAttr = GetFileAttributesA(pTempFrom);
601 }
602
603 PathAddBackslashA(pTempFrom);
604 lenTempFrom = strlen(pTempFrom);
605 pFromFile=&pTempFrom[lenTempFrom];
606
607 if (FromAttr == -1 ||
608 ((lenTempFrom==lenFrom) && !PathIsRootA(pFrom)) ||
609 !(FromAttr & FILE_ATTRIBUTE_DIRECTORY) ||
610 !(('\0'==pFrom[lenTempFrom]) || (0==strcmp(&pFrom[lenTempFrom],"*.*"))) ) {
611 retCode=0x402;
612 nlpFileOp.fAnyOperationsAborted=TRUE;
613 where = 303;
614 break;
615 }
616 strcpy(pFromFile, "*.*");
617 lenTempFrom = strlen(pTempFrom);
618 if (lenFrom < lenTempFrom) {
619// Source is without \*.*
620 pTempFrom[lenTempFrom+1]='\0';
621 nlpFileOp.pFrom = pTempFrom;
622
623 TRACE(__FUNCTION__" FO_DELETE level=%d Entering Directory '%s'\n",level , nlpFileOp.pFrom);
624 TempretCode = SHFileOperationA (&nlpFileOp);
625
626 if (nlpFileOp.fAnyOperationsAborted) {break;}
627// Call SHELL_DeleteDirectoryA ?
628 if (RemoveDirectoryA(pFrom)) continue;
629 nlpFileOp.fAnyOperationsAborted=TRUE;
630 where = 304;
631 break;
632 }
633 hFind = FindFirstFileA(pTempFrom, &wfd);
634 if (INVALID_HANDLE_VALUE == hFind) {
635 nlpFileOp.fAnyOperationsAborted=TRUE;
636 retCode=0x79;
637 where = 303;
638 break;
639 }
640
641 nlpFileOp.pFrom = pTempFrom;
642
643 nlpFileOp.fFlags = (nlpFileOp.fFlags & (-1 - (FOF_MULTIDESTFILES)));
644
645 TRACE(__FUNCTION__" FO_DELETE level=%d Delete in Subdir %s'\n",level , nlpFileOp.pFrom);
646
647 do {
648 TRACE(__FUNCTION__" FO_DELETE level=%d find '%s'\n",level , wfd.cFileName);
649 if (0==strcmp(wfd.cFileName,".")) continue;
650 if (0==strcmp(wfd.cFileName,"..")) continue;
651 if ((nlpFileOp.fFlags & FOF_FILESONLY) && (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)) {
652 continue;
653 } /* endif */
654
655 strcpy(pFromFile,wfd.cFileName);
656 pTempFrom[strlen(pTempFrom)+1]='\0';
657
658 TempretCode = SHFileOperationA (&nlpFileOp);
659
660 if (nlpFileOp.fAnyOperationsAborted) {where = 304;break;}
661
662 } while(FindNextFileA(hFind, &wfd));
663
664 FindClose(hFind);
665 if (nlpFileOp.fAnyOperationsAborted) {where = 305;break;}
666 continue;
667 }
668 break;
669 case FO_MOVE:
670 TRACE(__FUNCTION__" FO_MOVE level=%d File\\Tree Move: simply (Copy/Delete)\n",level);
671 nlpFileOp.wFunc = (level<<4) + FO_COPY;
672// not delete at error from copy
673 TempretCode = SHFileOperationA (&nlpFileOp);
674
675 if (nlpFileOp.fAnyOperationsAborted) {
676 if (TempretCode == 0x75) {
677// not all, the most
678 TempretCode = 0xD7;
679 retCode = 0xD7;
680 } /* endif */
681 break;
682 }
683
684 nlpFileOp.wFunc = (level<<4) + FO_DELETE;
685
686 TempretCode = SHFileOperationA (&nlpFileOp);
687
688 case 0:
689 break;
690#else
691 TRACE("File Delete:\n");
692 while(1) {
693 if(!pFrom[0]) break;
694 TRACE(" File='%s'\n", pFrom);
695 DeleteFileA(pFrom);
696 pFrom += strlen(pFrom) + 1;
697 }
698 TRACE("Setting AnyOpsAborted=FALSE\n");
699 lpFileOp->fAnyOperationsAborted=FALSE;
700 return 0;
701#endif
702
703 default:
704#ifdef __WIN32OS2__
705 TRACE(__FUNCTION__" Unhandled shell file operation %d at level=%d stub\n",(lpFileOp->wFunc & 15), level );
706 lpFileOp->fAnyOperationsAborted=TRUE;
707#else
708 FIXME("Unhandled shell file operation %d\n", lpFileOp->wFunc);
709 }
710#endif
711 return 1;
712
713#ifdef __WIN32OS2__
714 }
715 if (pTempFrom) HeapFree(GetProcessHeap(), 0, pTempFrom);
716
717 if (nlpFileOp.fAnyOperationsAborted) {
718 lpFileOp->fAnyOperationsAborted=TRUE;
719 if (TempretCode > retCode) {
720 retCode = TempretCode;
721 } /* endif */
722 }
723 if (lpFileOp->fAnyOperationsAborted==TRUE) {
724 if (FO_DELETE == (lpFileOp->wFunc & 15)) {
725 TRACE(__FUNCTION__" Setting AnyOpsAborted=TRUE level=%d ret=0x%x, at=%i with %s\n",level, retCode,where,pFrom);
726 } else {
727 TRACE(__FUNCTION__" Setting AnyOpsAborted=TRUE level=%d ret=0x%x, at=%i with %s -> %s\n",level, retCode,where,pFrom,pTo);
728 }
729 return retCode;
730 } /* endif */
731 TRACE(__FUNCTION__" Setting AnyOpsAborted=FALSE\n");
732 return 0;
733
734#endif
735}
736
737/*************************************************************************
738 * SHFileOperationW [SHELL32.244]
739 *
740 * NOTES
741 * exported by name
742 */
743DWORD WINAPI SHFileOperationW (LPSHFILEOPSTRUCTW lpFileOp)
744{
745 FIXME("(%p):stub.\n", lpFileOp);
746 return 1;
747}
748
749/*************************************************************************
750 * SHFileOperation [SHELL32.242]
751 *
752 */
753DWORD WINAPI SHFileOperationAW(LPVOID lpFileOp)
754{
755 if (SHELL_OsIsUnicode())
756 return SHFileOperationW(lpFileOp);
757 return SHFileOperationA(lpFileOp);
758}
759
760/*************************************************************************
761 * SheGetDirW [SHELL32.281]
762 *
763 */
764HRESULT WINAPI SheGetDirW(LPWSTR u, LPWSTR v)
765{ FIXME("%p %p stub\n",u,v);
766 return 0;
767}
768
769/*************************************************************************
770 * SheChangeDirW [SHELL32.274]
771 *
772 */
773HRESULT WINAPI SheChangeDirW(LPWSTR u)
774{ FIXME("(%s),stub\n",debugstr_w(u));
775 return 0;
776}
777
778/*************************************************************************
779 * IsNetDrive [SHELL32.66]
780 */
781BOOL WINAPI IsNetDrive(DWORD drive)
782{
783 char root[4];
784 strcpy(root, "A:\\");
785 root[0] += drive;
786 return (GetDriveTypeA(root) == DRIVE_REMOTE);
787}
788
789
790
Note: See TracBrowser for help on using the repository browser.