4 * Copyright 2000 Juergen Schmied
5 * Copyright 2002 Andriy Palamarchuk
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.
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.
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
23 #include "wine/port.h"
32 #include "shell32_main.h"
33 #include "undocshell.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
39 #define IsAttribFile(x) (!(x == -1) && !(x & FILE_ATTRIBUTE_DIRECTORY))
40 #define IsAttribDir(x) (!(x == -1) && (x & FILE_ATTRIBUTE_DIRECTORY))
42 #define IsDotDir(x) ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))))
44 CHAR aWildcardFile
[] = {'*','.','*',0};
45 WCHAR wWildcardFile
[] = {'*','.','*',0};
46 WCHAR wWildcardChars
[] = {'*','?',0};
47 WCHAR wBackslash
[] = {'\\',0};
49 static BOOL
SHNotifyCreateDirectoryA(LPCSTR path
, LPSECURITY_ATTRIBUTES sec
);
50 static BOOL
SHNotifyCreateDirectoryW(LPCWSTR path
, LPSECURITY_ATTRIBUTES sec
);
51 static BOOL
SHNotifyRemoveDirectoryA(LPCSTR path
);
52 static BOOL
SHNotifyRemoveDirectoryW(LPCWSTR path
);
53 static BOOL
SHNotifyDeleteFileA(LPCSTR path
);
54 static BOOL
SHNotifyDeleteFileW(LPCWSTR path
);
55 static BOOL
SHNotifyMoveFileW(LPCWSTR src
, LPCWSTR dest
);
56 static BOOL
SHNotifyCopyFileW(LPCWSTR src
, LPCWSTR dest
, BOOL bRenameIfExists
);
60 UINT caption_resource_id
, text_resource_id
;
61 } SHELL_ConfirmIDstruc
;
63 static BOOL
SHELL_ConfirmIDs(int nKindOfDialog
, SHELL_ConfirmIDstruc
*ids
)
65 switch (nKindOfDialog
) {
67 ids
->caption_resource_id
= IDS_DELETEITEM_CAPTION
;
68 ids
->text_resource_id
= IDS_DELETEITEM_TEXT
;
70 case ASK_DELETE_FOLDER
:
71 ids
->caption_resource_id
= IDS_DELETEFOLDER_CAPTION
;
72 ids
->text_resource_id
= IDS_DELETEITEM_TEXT
;
74 case ASK_DELETE_MULTIPLE_ITEM
:
75 ids
->caption_resource_id
= IDS_DELETEITEM_CAPTION
;
76 ids
->text_resource_id
= IDS_DELETEMULTIPLE_TEXT
;
78 case ASK_OVERWRITE_FILE
:
79 ids
->caption_resource_id
= IDS_OVERWRITEFILE_CAPTION
;
80 ids
->text_resource_id
= IDS_OVERWRITEFILE_TEXT
;
83 FIXME(" Unhandled nKindOfDialog %d stub\n", nKindOfDialog
);
88 BOOL
SHELL_ConfirmDialog(int nKindOfDialog
, LPCSTR szDir
)
90 CHAR szCaption
[255], szText
[255], szBuffer
[MAX_PATH
+ 256];
91 SHELL_ConfirmIDstruc ids
;
93 if (!SHELL_ConfirmIDs(nKindOfDialog
, &ids
))
96 LoadStringA(shell32_hInstance
, ids
.caption_resource_id
, szCaption
, sizeof(szCaption
));
97 LoadStringA(shell32_hInstance
, ids
.text_resource_id
, szText
, sizeof(szText
));
99 FormatMessageA(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
100 szText
, 0, 0, szBuffer
, sizeof(szBuffer
), (va_list*)&szDir
);
102 return (IDOK
== MessageBoxA(GetActiveWindow(), szBuffer
, szCaption
, MB_OKCANCEL
| MB_ICONEXCLAMATION
));
105 BOOL
SHELL_ConfirmDialogW(int nKindOfDialog
, LPCWSTR szDir
)
107 WCHAR szCaption
[255], szText
[255], szBuffer
[MAX_PATH
+ 256];
108 SHELL_ConfirmIDstruc ids
;
110 if (!SHELL_ConfirmIDs(nKindOfDialog
, &ids
))
113 LoadStringW(shell32_hInstance
, ids
.caption_resource_id
, szCaption
, sizeof(szCaption
));
114 LoadStringW(shell32_hInstance
, ids
.text_resource_id
, szText
, sizeof(szText
));
116 FormatMessageW(FORMAT_MESSAGE_FROM_STRING
|FORMAT_MESSAGE_ARGUMENT_ARRAY
,
117 szText
, 0, 0, szBuffer
, sizeof(szBuffer
), (va_list*)&szDir
);
119 return (IDOK
== MessageBoxW(GetActiveWindow(), szBuffer
, szCaption
, MB_OKCANCEL
| MB_ICONEXCLAMATION
));
122 /**************************************************************************
123 * SHELL_DeleteDirectoryA() [internal]
127 BOOL
SHELL_DeleteDirectoryA(LPCSTR pszDir
, BOOL bShowUI
)
131 WIN32_FIND_DATAA wfd
;
132 char szTemp
[MAX_PATH
];
134 /* Make sure the directory exists before eventually prompting the user */
135 PathCombineA(szTemp
, pszDir
, aWildcardFile
);
136 hFind
= FindFirstFileA(szTemp
, &wfd
);
137 if (hFind
== INVALID_HANDLE_VALUE
)
140 if (!bShowUI
|| SHELL_ConfirmDialog(ASK_DELETE_FOLDER
, pszDir
))
144 LPSTR lp
= wfd
.cAlternateFileName
;
149 PathCombineA(szTemp
, pszDir
, lp
);
150 if (FILE_ATTRIBUTE_DIRECTORY
& wfd
.dwFileAttributes
)
151 ret
= SHELL_DeleteDirectoryA(szTemp
, FALSE
);
153 ret
= SHNotifyDeleteFileA(szTemp
);
154 } while (ret
&& FindNextFileA(hFind
, &wfd
));
158 ret
= SHNotifyRemoveDirectoryA(pszDir
);
162 BOOL
SHELL_DeleteDirectoryW(LPCWSTR pszDir
, BOOL bShowUI
)
166 WIN32_FIND_DATAW wfd
;
167 WCHAR szTemp
[MAX_PATH
];
169 /* Make sure the directory exists before eventually prompting the user */
170 PathCombineW(szTemp
, pszDir
, wWildcardFile
);
171 hFind
= FindFirstFileW(szTemp
, &wfd
);
172 if (hFind
== INVALID_HANDLE_VALUE
)
175 if (!bShowUI
|| SHELL_ConfirmDialogW(ASK_DELETE_FOLDER
, pszDir
))
179 LPWSTR lp
= wfd
.cAlternateFileName
;
184 PathCombineW(szTemp
, pszDir
, lp
);
185 if (FILE_ATTRIBUTE_DIRECTORY
& wfd
.dwFileAttributes
)
186 ret
= SHELL_DeleteDirectoryW(szTemp
, FALSE
);
188 ret
= SHNotifyDeleteFileW(szTemp
);
189 } while (ret
&& FindNextFileW(hFind
, &wfd
));
193 ret
= SHNotifyRemoveDirectoryW(pszDir
);
197 /**************************************************************************
198 * SHELL_DeleteFileA() [internal]
200 BOOL
SHELL_DeleteFileA(LPCSTR pszFile
, BOOL bShowUI
)
202 if (bShowUI
&& !SHELL_ConfirmDialog(ASK_DELETE_FILE
, pszFile
))
205 return SHNotifyDeleteFileA(pszFile
);
208 BOOL
SHELL_DeleteFileW(LPCWSTR pszFile
, BOOL bShowUI
)
210 if (bShowUI
&& !SHELL_ConfirmDialogW(ASK_DELETE_FILE
, pszFile
))
213 return SHNotifyDeleteFileW(pszFile
);
216 /**************************************************************************
217 * Win32CreateDirectory [SHELL32.93]
219 * Creates a directory. Also triggers a change notify if one exists.
222 * path [I] path to directory to create
225 * TRUE if successful, FALSE otherwise
228 * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI.
229 * This is Unicode on NT/2000
232 static BOOL
SHNotifyCreateDirectoryA(LPCSTR path
, LPSECURITY_ATTRIBUTES sec
)
235 TRACE("(%s, %p)\n", debugstr_a(path
), sec
);
237 ret
= CreateDirectoryA(path
, sec
);
240 SHChangeNotify(SHCNE_MKDIR
, SHCNF_PATHA
, path
, NULL
);
245 static BOOL
SHNotifyCreateDirectoryW(LPCWSTR path
, LPSECURITY_ATTRIBUTES sec
)
248 TRACE("(%s, %p)\n", debugstr_w(path
), sec
);
250 ret
= CreateDirectoryW(path
, sec
);
253 SHChangeNotify(SHCNE_MKDIR
, SHCNF_PATHW
, path
, NULL
);
258 BOOL WINAPI
Win32CreateDirectoryAW(LPCVOID path
, LPSECURITY_ATTRIBUTES sec
)
260 if (SHELL_OsIsUnicode())
261 return SHNotifyCreateDirectoryW(path
, sec
);
262 return SHNotifyCreateDirectoryA(path
, sec
);
265 /************************************************************************
266 * Win32RemoveDirectory [SHELL32.94]
268 * Deletes a directory. Also triggers a change notify if one exists.
271 * path [I] path to directory to delete
274 * TRUE if successful, FALSE otherwise
277 * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI.
278 * This is Unicode on NT/2000
280 static BOOL
SHNotifyRemoveDirectoryA(LPCSTR path
)
283 TRACE("(%s)\n", debugstr_a(path
));
285 ret
= RemoveDirectoryA(path
);
288 /* Directory may be write protected */
289 DWORD dwAttr
= GetFileAttributesA(path
);
290 if (dwAttr
!= -1 && dwAttr
& FILE_ATTRIBUTE_READONLY
)
291 if (SetFileAttributesA(path
, dwAttr
& ~FILE_ATTRIBUTE_READONLY
))
292 ret
= RemoveDirectoryA(path
);
295 SHChangeNotify(SHCNE_RMDIR
, SHCNF_PATHA
, path
, NULL
);
299 static BOOL
SHNotifyRemoveDirectoryW(LPCWSTR path
)
302 TRACE("(%s)\n", debugstr_w(path
));
304 ret
= RemoveDirectoryW(path
);
307 /* Directory may be write protected */
308 DWORD dwAttr
= GetFileAttributesW(path
);
309 if (dwAttr
!= -1 && dwAttr
& FILE_ATTRIBUTE_READONLY
)
310 if (SetFileAttributesW(path
, dwAttr
& ~FILE_ATTRIBUTE_READONLY
))
311 ret
= RemoveDirectoryW(path
);
314 SHChangeNotify(SHCNE_RMDIR
, SHCNF_PATHW
, path
, NULL
);
318 BOOL WINAPI
Win32RemoveDirectoryAW(LPCVOID path
)
320 if (SHELL_OsIsUnicode())
321 return SHNotifyRemoveDirectoryW(path
);
322 return SHNotifyRemoveDirectoryA(path
);
325 /************************************************************************
326 * Win32DeleteFile [SHELL32.164]
328 * Deletes a file. Also triggers a change notify if one exists.
331 * path [I] path to file to delete
334 * TRUE if successful, FALSE otherwise
337 * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be ANSI.
338 * This is Unicode on NT/2000
340 static BOOL
SHNotifyDeleteFileA(LPCSTR path
)
344 TRACE("(%s)\n", debugstr_a(path
));
346 ret
= DeleteFileA(path
);
349 /* File may be write protected or a system file */
350 DWORD dwAttr
= GetFileAttributesA(path
);
351 if ((dwAttr
!= -1) && (dwAttr
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_SYSTEM
)))
352 if (SetFileAttributesA(path
, dwAttr
& ~(FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_SYSTEM
)))
353 ret
= DeleteFileA(path
);
356 SHChangeNotify(SHCNE_DELETE
, SHCNF_PATHA
, path
, NULL
);
360 static BOOL
SHNotifyDeleteFileW(LPCWSTR path
)
364 TRACE("(%s)\n", debugstr_w(path
));
366 ret
= DeleteFileW(path
);
369 /* File may be write protected or a system file */
370 DWORD dwAttr
= GetFileAttributesW(path
);
371 if ((dwAttr
!= -1) && (dwAttr
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_SYSTEM
)))
372 if (SetFileAttributesW(path
, dwAttr
& ~(FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_SYSTEM
)))
373 ret
= DeleteFileW(path
);
376 SHChangeNotify(SHCNE_DELETE
, SHCNF_PATHW
, path
, NULL
);
380 DWORD WINAPI
Win32DeleteFileAW(LPCVOID path
)
382 if (SHELL_OsIsUnicode())
383 return SHNotifyDeleteFileW(path
);
384 return SHNotifyDeleteFileA(path
);
387 /************************************************************************
388 * SHNotifyMoveFile [internal]
390 * Moves a file. Also triggers a change notify if one exists.
393 * src [I] path to source file to move
394 * dest [I] path to target file to move to
397 * TRUE if successful, FALSE otherwise
399 static BOOL
SHNotifyMoveFileW(LPCWSTR src
, LPCWSTR dest
)
403 TRACE("(%s %s)\n", debugstr_w(src
), debugstr_w(dest
));
405 ret
= MoveFileW(src
, dest
);
408 /* Source file may be write protected or a system file */
409 DWORD dwAttr
= GetFileAttributesW(src
);
410 if ((dwAttr
!= -1) && (dwAttr
& (FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_SYSTEM
)))
411 if (SetFileAttributesW(src
, dwAttr
& ~(FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_SYSTEM
)))
412 ret
= MoveFileW(src
, dest
);
415 SHChangeNotify(SHCNE_RENAMEITEM
, SHCNF_PATHW
, src
, dest
);
419 /************************************************************************
420 * SHNotifyCopyFile [internal]
422 * Copies a file. Also triggers a change notify if one exists.
425 * src [I] path to source file to move
426 * dest [I] path to target file to move to
427 * bRename [I] if TRUE, the target file will be renamed if a
428 * file with this name already exists
431 * TRUE if successful, FALSE otherwise
433 static BOOL
SHNotifyCopyFileW(LPCWSTR src
, LPCWSTR dest
, BOOL bRename
)
437 TRACE("(%s %s %s)\n", debugstr_w(src
), debugstr_w(dest
), bRename
? "renameIfExists" : "");
439 ret
= CopyFileW(src
, dest
, TRUE
);
442 /* Destination file probably exists */
443 DWORD dwAttr
= GetFileAttributesW(dest
);
446 FIXME("Rename on copy to existing file not implemented!");
450 SHChangeNotify(SHCNE_CREATE
, SHCNF_PATHW
, dest
, NULL
);
454 /*************************************************************************
455 * SHCreateDirectory [SHELL32.165]
457 * Create a directory at the specified location
461 * path [I] path of directory to create
464 * ERRROR_SUCCESS or one of the following values:
465 * ERROR_BAD_PATHNAME if the path is relative
466 * ERROR_FILE_EXISTS when a file with that name exists
467 * ERROR_ALREADY_EXISTS when the directory already exists
468 * ERROR_FILENAME_EXCED_RANGE if the filename was to long to process
471 * exported by ordinal
473 * WinNT/2000 exports Unicode
475 DWORD WINAPI
SHCreateDirectory(HWND hWnd
, LPCVOID path
)
477 if (SHELL_OsIsUnicode())
478 return SHCreateDirectoryExW(hWnd
, path
, NULL
);
479 return SHCreateDirectoryExA(hWnd
, path
, NULL
);
482 /*************************************************************************
483 * SHCreateDirectoryExA [SHELL32.@]
485 * Create a directory at the specified location
489 * path [I] path of directory to create
490 * sec [I] security attributes to use or NULL
493 * ERRROR_SUCCESS or one of the following values:
494 * ERROR_BAD_PATHNAME if the path is relative
495 * ERROR_FILE_EXISTS when a file with that name exists
496 * ERROR_ALREADY_EXISTS when the directory already exists
497 * ERROR_FILENAME_EXCED_RANGE if the filename was to long to process
499 DWORD WINAPI
SHCreateDirectoryExA(HWND hWnd
, LPCSTR path
, LPSECURITY_ATTRIBUTES sec
)
501 WCHAR wPath
[MAX_PATH
];
502 TRACE("(%p, %s, %p)\n",hWnd
, debugstr_a(path
), sec
);
504 MultiByteToWideChar(CP_ACP
, 0, path
, -1, wPath
, MAX_PATH
);
505 return SHCreateDirectoryExW(hWnd
, wPath
, sec
);
508 /*************************************************************************
509 * SHCreateDirectoryExW [SHELL32.@]
511 DWORD WINAPI
SHCreateDirectoryExW(HWND hWnd
, LPCWSTR path
, LPSECURITY_ATTRIBUTES sec
)
513 DWORD ret
= ERROR_SUCCESS
;
514 TRACE("(%p, %s, %p)\n",hWnd
, debugstr_w(path
), sec
);
516 if (PathIsRelativeW(path
))
518 ret
= ERROR_BAD_PATHNAME
;
519 SetLastError(ERROR_BAD_PATHNAME
);
523 if (!SHNotifyCreateDirectoryW(path
, sec
))
525 ret
= GetLastError();
526 if (ret
!= ERROR_FILE_EXISTS
&&
527 ret
!= ERROR_ALREADY_EXISTS
&&
528 ret
!= ERROR_FILENAME_EXCED_RANGE
)
530 /* handling network file names?
531 lstrcpynW(pathName, path, MAX_PATH);
532 lpStr = PathAddBackslashW(pathName);*/
533 FIXME("Semi-stub, non zero hWnd should be used somehow?");
540 /**************************************************************************
541 * SHELL_FileNamesMatch()
543 * Accepts two \0 delimited lists of the file names. Checks whether number of
544 * files in the both lists is the same.
546 BOOL
SHELL_FileNamesMatch(LPCSTR pszFiles1
, LPCSTR pszFiles2
)
548 while ((pszFiles1
[strlen(pszFiles1
) + 1] != '\0') &&
549 (pszFiles2
[strlen(pszFiles2
) + 1] != '\0'))
551 pszFiles1
+= strlen(pszFiles1
) + 1;
552 pszFiles2
+= strlen(pszFiles2
) + 1;
556 ((pszFiles1
[strlen(pszFiles1
) + 1] == '\0') &&
557 (pszFiles2
[strlen(pszFiles2
) + 1] == '\0')) ||
558 ((pszFiles1
[strlen(pszFiles1
) + 1] != '\0') &&
559 (pszFiles2
[strlen(pszFiles2
) + 1] != '\0'));
562 /*************************************************************************
563 * SHFileOperationA [SHELL32.@]
568 DWORD WINAPI
SHFileOperationA (LPSHFILEOPSTRUCTA lpFileOp
)
570 LPSTR pFrom
= (LPSTR
)lpFileOp
->pFrom
;
571 LPSTR pTo
= (LPSTR
)lpFileOp
->pTo
;
573 TRACE("flags (0x%04x) : %s%s%s%s%s%s%s%s%s%s%s%s \n", lpFileOp
->fFlags
,
574 lpFileOp
->fFlags
& FOF_MULTIDESTFILES
? "FOF_MULTIDESTFILES " : "",
575 lpFileOp
->fFlags
& FOF_CONFIRMMOUSE
? "FOF_CONFIRMMOUSE " : "",
576 lpFileOp
->fFlags
& FOF_SILENT
? "FOF_SILENT " : "",
577 lpFileOp
->fFlags
& FOF_RENAMEONCOLLISION
? "FOF_RENAMEONCOLLISION " : "",
578 lpFileOp
->fFlags
& FOF_NOCONFIRMATION
? "FOF_NOCONFIRMATION " : "",
579 lpFileOp
->fFlags
& FOF_WANTMAPPINGHANDLE
? "FOF_WANTMAPPINGHANDLE " : "",
580 lpFileOp
->fFlags
& FOF_ALLOWUNDO
? "FOF_ALLOWUNDO " : "",
581 lpFileOp
->fFlags
& FOF_FILESONLY
? "FOF_FILESONLY " : "",
582 lpFileOp
->fFlags
& FOF_SIMPLEPROGRESS
? "FOF_SIMPLEPROGRESS " : "",
583 lpFileOp
->fFlags
& FOF_NOCONFIRMMKDIR
? "FOF_NOCONFIRMMKDIR " : "",
584 lpFileOp
->fFlags
& FOF_NOERRORUI
? "FOF_NOERRORUI " : "",
585 lpFileOp
->fFlags
& 0xf800 ? "MORE-UNKNOWN-Flags" : "");
586 switch(lpFileOp
->wFunc
) {
590 /* establish when pTo is interpreted as the name of the destination file
591 * or the directory where the Fromfile should be copied to.
593 * (1) pTo points to the name of an existing directory;
594 * (2) the flag FOF_MULTIDESTFILES is present;
595 * (3) whether pFrom point to multiple filenames.
599 * destisdir 1 1 1 1 0 0 0 0
600 * FOF_MULTIDESTFILES 1 1 0 0 1 1 0 0
601 * multiple from filenames 1 0 1 0 1 0 1 0
603 * copy files to dir 1 0 1 1 0 0 1 0
604 * create dir 0 0 0 0 0 0 1 0
606 int multifrom
= pFrom
[strlen(pFrom
) + 1] != '\0';
607 int destisdir
= PathIsDirectoryA( pTo
);
610 if (lpFileOp
->wFunc
== FO_COPY
)
611 TRACE("File Copy:\n");
613 TRACE("File Move:\n");
616 if ( !((lpFileOp
->fFlags
& FOF_MULTIDESTFILES
) && !multifrom
))
619 if ( !(lpFileOp
->fFlags
& FOF_MULTIDESTFILES
) && multifrom
)
623 if ((pTo
[strlen(pTo
) + 1] != '\0') &&
624 !(lpFileOp
->fFlags
& FOF_MULTIDESTFILES
))
626 WARN("Attempt to use multiple file names as a destination "
627 "without specifying FOF_MULTIDESTFILES\n");
631 if ((lpFileOp
->fFlags
& FOF_MULTIDESTFILES
) &&
632 !SHELL_FileNamesMatch(pTo
, pFrom
))
634 WARN("Attempt to use multiple file names as a destination "
635 "with mismatching number of files in the source and "
636 "destination lists\n");
641 char szTempFrom
[MAX_PATH
];
645 TRACE(" creating directory %s\n",pTo
);
646 SHCreateDirectoryExA(NULL
, pTo
, NULL
);
648 lenPTo
= strlen(pTo
);
651 WIN32_FIND_DATAA wfd
;
654 TRACE(" From Pattern='%s'\n", pFrom
);
655 if(INVALID_HANDLE_VALUE
!= (hFind
= FindFirstFileA(pFrom
, &wfd
)))
659 if(strcasecmp(wfd
.cFileName
, ".") && strcasecmp(wfd
.cFileName
, ".."))
661 strcpy(szTempFrom
, pFrom
);
663 pTempTo
= HeapAlloc(GetProcessHeap(), 0,
664 lenPTo
+ strlen(wfd
.cFileName
) + 5);
667 PathAddBackslashA(pTempTo
);
668 strcat(pTempTo
,wfd
.cFileName
);
670 fromfile
= PathFindFileNameA(szTempFrom
);
672 PathAddBackslashA(szTempFrom
);
673 strcat(szTempFrom
, wfd
.cFileName
);
674 TRACE(" From='%s' To='%s'\n", szTempFrom
, pTempTo
);
675 if(lpFileOp
->wFunc
== FO_COPY
)
677 if(FILE_ATTRIBUTE_DIRECTORY
& wfd
.dwFileAttributes
)
679 /* copy recursively */
680 if(!(lpFileOp
->fFlags
& FOF_FILESONLY
))
682 SHFILEOPSTRUCTA shfo
;
684 SHCreateDirectoryExA(NULL
, pTempTo
, NULL
);
685 PathAddBackslashA(szTempFrom
);
686 strcat(szTempFrom
, "*.*");
687 szTempFrom
[strlen(szTempFrom
) + 1] = '\0';
688 pTempTo
[strlen(pTempTo
) + 1] = '\0';
689 memcpy(&shfo
, lpFileOp
, sizeof(shfo
));
690 shfo
.pFrom
= szTempFrom
;
692 SHFileOperationA(&shfo
);
694 szTempFrom
[strlen(szTempFrom
) - 4] = '\0';
698 CopyFileA(szTempFrom
, pTempTo
, FALSE
);
702 /* move file/directory */
703 MoveFileA(szTempFrom
, pTempTo
);
705 HeapFree(GetProcessHeap(), 0, pTempTo
);
708 } while(FindNextFileA(hFind
, &wfd
));
713 /* can't find file with specified name */
716 pFrom
+= strlen(pFrom
) + 1;
722 TRACE(" From='%s' To='%s'\n", pFrom
, pTo
);
724 pTempTo
= HeapAlloc(GetProcessHeap(), 0, strlen(pTo
)+1);
727 strcpy( pTempTo
, pTo
);
728 PathRemoveFileSpecA(pTempTo
);
729 TRACE(" Creating Directory '%s'\n", pTempTo
);
730 SHCreateDirectoryExA(NULL
, pTempTo
, NULL
);
731 HeapFree(GetProcessHeap(), 0, pTempTo
);
733 if (lpFileOp
->wFunc
== FO_COPY
)
734 CopyFileA(pFrom
, pTo
, FALSE
);
736 MoveFileA(pFrom
, pTo
);
738 pFrom
+= strlen(pFrom
) + 1;
739 pTo
+= strlen(pTo
) + 1;
742 TRACE("Setting AnyOpsAborted=FALSE\n");
743 lpFileOp
->fAnyOperationsAborted
=FALSE
;
750 WIN32_FIND_DATAA wfd
;
751 char szTemp
[MAX_PATH
];
754 TRACE("File Delete:\n");
757 TRACE(" Pattern='%s'\n", pFrom
);
758 if(INVALID_HANDLE_VALUE
!= (hFind
= FindFirstFileA(pFrom
, &wfd
)))
762 if(strcasecmp(wfd
.cFileName
, ".") && strcasecmp(wfd
.cFileName
, ".."))
764 strcpy(szTemp
, pFrom
);
765 file_name
= PathFindFileNameA(szTemp
);
767 PathAddBackslashA(szTemp
);
768 strcat(szTemp
, wfd
.cFileName
);
770 TRACE(" File='%s'\n", szTemp
);
771 if(FILE_ATTRIBUTE_DIRECTORY
& wfd
.dwFileAttributes
)
773 if(!(lpFileOp
->fFlags
& FOF_FILESONLY
))
774 SHELL_DeleteDirectoryA(szTemp
, FALSE
);
779 } while(FindNextFileA(hFind
, &wfd
));
783 pFrom
+= strlen(pFrom
) + 1;
785 TRACE("Setting AnyOpsAborted=FALSE\n");
786 lpFileOp
->fAnyOperationsAborted
=FALSE
;
791 TRACE("File Rename:\n");
792 if (pFrom
[strlen(pFrom
) + 1] != '\0')
794 WARN("Attempt to rename more than one file\n");
797 lpFileOp
->fAnyOperationsAborted
= FALSE
;
798 TRACE("From %s, To %s\n", pFrom
, pTo
);
799 return !MoveFileA(pFrom
, pTo
);
802 FIXME("Unhandled shell file operation %d\n", lpFileOp
->wFunc
);
808 /*************************************************************************
809 * SHFileOperationW [SHELL32.@]
814 DWORD WINAPI
SHFileOperationW (LPSHFILEOPSTRUCTW lpFileOp
)
816 FIXME("(%p):stub.\n", lpFileOp
);
820 /*************************************************************************
821 * SHFileOperation [SHELL32.@]
824 DWORD WINAPI
SHFileOperationAW(LPVOID lpFileOp
)
826 if (SHELL_OsIsUnicode())
827 return SHFileOperationW(lpFileOp
);
828 return SHFileOperationA(lpFileOp
);
831 /*************************************************************************
832 * SheGetDirW [SHELL32.281]
835 HRESULT WINAPI
SheGetDirW(LPWSTR u
, LPWSTR v
)
836 { FIXME("%p %p stub\n",u
,v
);
840 /*************************************************************************
841 * SheChangeDirW [SHELL32.274]
844 HRESULT WINAPI
SheChangeDirW(LPWSTR u
)
845 { FIXME("(%s),stub\n",debugstr_w(u
));
849 /*************************************************************************
850 * IsNetDrive [SHELL32.66]
852 BOOL WINAPI
IsNetDrive(DWORD drive
)
855 strcpy(root
, "A:\\");
856 root
[0] += (char)drive
;
857 return (GetDriveTypeA(root
) == DRIVE_REMOTE
);