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

Last change on this file since 5611 was 5576, checked in by sandervl, 24 years ago

Updates and fixes for SHFileOperationA (FO_COPY)

File size: 14.4 KB
Line 
1/*
2 * SHFileOperation
3 */
4#ifdef __WIN32OS2__
5#define ICOM_CINTERFACE 1
6#include <odin.h>
7#endif
8#include <string.h>
9#include "debugtools.h"
10#include "shellapi.h"
11#include "shlwapi.h"
12
13#include "shlobj.h"
14#include "shresdef.h"
15#include "shell32_main.h"
16#include "wine/undocshell.h"
17#include "shlwapi.h"
18
19DEFAULT_DEBUG_CHANNEL(shell);
20
21
22#ifdef __WIN32OS2__
23BOOL SHELL_ConfirmDialog (int nKindOfDialog, LPCSTR szDir)
24{
25 char szCaption[255], szText[255], szBuffer[MAX_PATH + 256];
26 UINT caption_resource_id, text_resource_id;
27
28 switch(nKindOfDialog) {
29
30 case ASK_DELETE_FILE:
31 caption_resource_id = IDS_DELETEITEM_CAPTION;
32 text_resource_id = IDS_DELETEITEM_TEXT;
33 break;
34 case ASK_DELETE_FOLDER:
35 caption_resource_id = IDS_DELETEFOLDER_CAPTION;
36 text_resource_id = IDS_DELETEITEM_TEXT;
37 break;
38 case ASK_DELETE_MULTIPLE_ITEM:
39 caption_resource_id = IDS_DELETEITEM_CAPTION;
40 text_resource_id = IDS_DELETEMULTIPLE_TEXT;
41 break;
42 case ASK_OVERWRITE_FILE:
43 caption_resource_id = IDS_OVERWRITEFILE_CAPTION;
44 text_resource_id = IDS_OVERWRITEFILE_TEXT;
45 break;
46 default:
47 FIXME(__FUNCTION__" Unhandled nKindOfDialog %d stub\n", nKindOfDialog);
48 return FALSE;
49 }
50
51 LoadStringA(shell32_hInstance, caption_resource_id, szCaption, sizeof(szCaption));
52 LoadStringA(shell32_hInstance, text_resource_id, szText, sizeof(szText));
53#else
54BOOL SHELL_WarnItemDelete (int nKindOfDialog, LPCSTR szDir)
55{
56 char szCaption[255], szText[255], szBuffer[MAX_PATH + 256];
57
58 if(nKindOfDialog == ASK_DELETE_FILE)
59 {
60 LoadStringA(shell32_hInstance, IDS_DELETEITEM_TEXT, szText,
61 sizeof(szText));
62 LoadStringA(shell32_hInstance, IDS_DELETEITEM_CAPTION,
63 szCaption, sizeof(szCaption));
64 }
65 else if(nKindOfDialog == ASK_DELETE_FOLDER)
66 {
67 LoadStringA(shell32_hInstance, IDS_DELETEITEM_TEXT, szText,
68 sizeof(szText));
69 LoadStringA(shell32_hInstance, IDS_DELETEFOLDER_CAPTION,
70 szCaption, sizeof(szCaption));
71 }
72 else if(nKindOfDialog == ASK_DELETE_MULTIPLE_ITEM)
73 {
74 LoadStringA(shell32_hInstance, IDS_DELETEMULTIPLE_TEXT, szText,
75 sizeof(szText));
76 LoadStringA(shell32_hInstance, IDS_DELETEITEM_CAPTION,
77 szCaption, sizeof(szCaption));
78 }
79 else {
80 FIXME("Called without a valid nKindOfDialog specified!");
81 LoadStringA(shell32_hInstance, IDS_DELETEITEM_TEXT, szText,
82 sizeof(szText));
83 LoadStringA(shell32_hInstance, IDS_DELETEITEM_CAPTION,
84 szCaption, sizeof(szCaption));
85 }
86#endif
87 FormatMessageA(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
88 szText, 0, 0, szBuffer, sizeof(szBuffer), (va_list*)&szDir);
89
90 return (IDOK == MessageBoxA(GetActiveWindow(), szBuffer, szCaption, MB_OKCANCEL | MB_ICONEXCLAMATION));
91}
92
93/**************************************************************************
94 * SHELL_DeleteDirectoryA()
95 *
96 * like rm -r
97 */
98
99BOOL SHELL_DeleteDirectoryA(LPCSTR pszDir, BOOL bShowUI)
100{
101 BOOL ret = FALSE;
102 HANDLE hFind;
103 WIN32_FIND_DATAA wfd;
104 char szTemp[MAX_PATH];
105
106 strcpy(szTemp, pszDir);
107 PathAddBackslashA(szTemp);
108 strcat(szTemp, "*.*");
109
110 if (bShowUI && !SHELL_WarnItemDelete(ASK_DELETE_FOLDER, pszDir))
111 return FALSE;
112
113 if(INVALID_HANDLE_VALUE != (hFind = FindFirstFileA(szTemp, &wfd)))
114 {
115 do
116 {
117 if(strcasecmp(wfd.cFileName, ".") && strcasecmp(wfd.cFileName, ".."))
118 {
119 strcpy(szTemp, pszDir);
120 PathAddBackslashA(szTemp);
121 strcat(szTemp, wfd.cFileName);
122
123 if(FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
124 SHELL_DeleteDirectoryA(szTemp, FALSE);
125 else
126 DeleteFileA(szTemp);
127 }
128 } while(FindNextFileA(hFind, &wfd));
129
130 FindClose(hFind);
131 ret = RemoveDirectoryA(pszDir);
132 }
133
134 return ret;
135}
136
137/**************************************************************************
138 * SHELL_DeleteFileA()
139 */
140
141BOOL SHELL_DeleteFileA(LPCSTR pszFile, BOOL bShowUI)
142{
143 if (bShowUI && !SHELL_WarnItemDelete(ASK_DELETE_FILE, pszFile))
144 return FALSE;
145
146 return DeleteFileA(pszFile);
147}
148
149/*************************************************************************
150 * SHCreateDirectory [SHELL32.165]
151 *
152 * NOTES
153 * exported by ordinal
154 * not sure about LPSECURITY_ATTRIBUTES
155 */
156DWORD WINAPI SHCreateDirectory(LPSECURITY_ATTRIBUTES sec,LPCSTR path)
157{
158 DWORD ret;
159 TRACE("(%p,%s)\n",sec,path);
160 if ((ret = CreateDirectoryA(path,sec)))
161 {
162 SHChangeNotifyA(SHCNE_MKDIR, SHCNF_PATHA, path, NULL);
163 }
164 return ret;
165}
166
167/************************************************************************
168 * Win32DeleteFile [SHELL32.164]
169 *
170 * Deletes a file. Also triggers a change notify if one exists.
171 *
172 * FIXME:
173 * Verified on Win98 / IE 5 (SHELL32 4.72, March 1999 build) to be
174 * ANSI. Is this Unicode on NT?
175 *
176 */
177
178BOOL WINAPI Win32DeleteFile(LPSTR fName)
179{
180 TRACE("%p(%s)\n", fName, fName);
181
182 DeleteFileA(fName);
183 SHChangeNotifyA(SHCNE_DELETE, SHCNF_PATHA, fName, NULL);
184 return TRUE;
185}
186
187#ifdef __WIN32OS2__
188/************************************************************************
189 * Creation from dir for SHFileOperation (FO_COPY)
190 *
191 */
192
193LPSTR DirForFileOperationA (LPSTR pTo, DWORD *dwAttr, LPSHFILEOPSTRUCTA lpFileOp, BOOL toSingle)
194{
195
196 LPSTR pTempTo = NULL;
197 long lenTo;
198 BOOL withFileName = FALSE;
199 if(pTo[0]) {
200 lenTo = strlen(pTo);
201 pTempTo = HeapAlloc(GetProcessHeap(), 0, lenTo + MAX_PATH);
202
203 }
204 *dwAttr = -1;
205 if (pTempTo) {
206 strcpy(pTempTo,pTo);
207 PathRemoveBackslashA(pTempTo);
208 *dwAttr = GetFileAttributesA(pTempTo);
209 if (*(dwAttr) == -1 || !(*(dwAttr) & FILE_ATTRIBUTE_DIRECTORY)) {
210 withFileName = ((lenTo == strlen(pTempTo)) || !toSingle);
211 if (withFileName) {
212// Target must not be an directory
213 PathRemoveFileSpecA(pTempTo);
214 *(dwAttr) = GetFileAttributesA(pTempTo);
215 }
216 }
217 if ((*(dwAttr) == -1) ||
218 ( !(*(dwAttr) & FILE_ATTRIBUTE_DIRECTORY) || (!withFileName && !toSingle) )) {
219// !toSingle == !(&pTo[strlen(pTo)+1]=="\0") redundant ?
220 if (!withFileName && !toSingle) {
221 FIXME(__FUNCTION__" FO_COPY tagetdir and FOF_MULTIDESTFILES not implemented ? ,stub\n");
222 };
223// never Create directory at this time
224 HeapFree(GetProcessHeap(), 0, pTempTo);
225 pTempTo = NULL;
226// }
227 }
228 }
229 if (!pTempTo) lpFileOp->fAnyOperationsAborted=TRUE;
230 return pTempTo;
231}
232#endif
233
234/*************************************************************************
235 * SHFileOperationA [SHELL32.243]
236 *
237 * NOTES
238 * exported by name
239 */
240DWORD WINAPI SHFileOperationA (LPSHFILEOPSTRUCTA lpFileOp)
241{
242 LPSTR pFrom = (LPSTR)lpFileOp->pFrom;
243 LPSTR pTo = (LPSTR)lpFileOp->pTo;
244#ifdef __WIN32OS2__
245 DWORD ToAttr;
246 DWORD FromAttr;
247 LPSTR pToFile;
248 LPSTR pTempTo = NULL;
249 LPSTR pTempFrom;
250
251 FILEOP_FLAGS OFl = ((FILEOP_FLAGS)lpFileOp->fFlags & 0x7ff);
252 BOOL Multi = (lpFileOp->fFlags & FOF_MULTIDESTFILES);
253 BOOL withFileName = FALSE;
254 BOOL not_overwrite;
255 BOOL copyOk;
256 long lenTo;
257/* default no error
258*/
259 lpFileOp->fAnyOperationsAborted=FALSE;
260#else
261 LPSTR pTempTo;
262#endif
263
264 switch(lpFileOp->wFunc) {
265 case FO_COPY:
266 TRACE("File Copy:\n");
267#ifdef __WIN32OS2__
268/*
269 * FOF_MULTIDESTFILES, FOF_NOCONFIRMATION are implemented
270 * FOF_CONFIRMMOUSE, FOF_SILENT, FOF_NOCONFIRMMKDIR, FOF_SIMPLEPROGRESS are not implemented and ignored
271 * if any other flag set, an error occurs
272 */
273 OFl = (OFl & (-1 - (FOF_MULTIDESTFILES)));
274 OFl = (OFl ^ (FOF_SILENT | FOF_NOCONFIRMATION | FOF_SIMPLEPROGRESS | FOF_NOCONFIRMMKDIR));
275 if (OFl) {
276 if (OFl & (-1 - (FOF_CONFIRMMOUSE | FOF_SILENT | FOF_NOCONFIRMATION | FOF_SIMPLEPROGRESS | FOF_NOCONFIRMMKDIR))) {
277 FIXME(__FUNCTION__" FO_COPY with this fFlags not implemented:%2x ,stub\n",lpFileOp->fFlags);
278 lpFileOp->fAnyOperationsAborted=TRUE;
279 } else {
280// not FOF_SILENT, not FOF_SIMPLEPROGRESS, not FOF_NOCONFIRMMKDIR
281 FIXME(__FUNCTION__" FO_COPY with this fFlags not full implemented:%2x ,stub\n",lpFileOp->fFlags);
282 } /* endif */
283 } /* endif */
284
285 not_overwrite = (!(lpFileOp->fFlags & FOF_NOCONFIRMATION));
286 while(!Multi && !lpFileOp->fAnyOperationsAborted) {
287// single targetdir
288 pTempTo = DirForFileOperationA(pTo, &ToAttr, lpFileOp, TRUE);
289
290 if (!pTempTo) break;
291
292 lenTo = strlen(pTempTo);
293 withFileName = (((lenTo + 1) < strlen(pTo)) || (PathIsRootA(pTo) && lenTo < strlen(pTo)));
294 PathAddBackslashA(pTempTo);
295 break;
296 }
297 if (!lpFileOp->fAnyOperationsAborted) {
298 TRACE("File Copy:\n");
299#ifdef __WIN32OS2__
300 while(pFrom[0]) {
301#endif
302 if(!pTo[0]) break;
303
304 TRACE(" From='%s' To='%s'\n", pFrom, pTo);
305
306 if (Multi) {
307// multi target, each one for one source. ? last
308 pTempTo = DirForFileOperationA(pTo, &ToAttr, lpFileOp, FALSE);
309 if (pTempTo) {
310
311 lenTo = strlen(pTempTo);
312 withFileName = (((lenTo + 1) < strlen(pTo)) || (PathIsRootA(pTo) && lenTo < strlen(pTo)));
313 PathAddBackslashA(pTempTo);
314 }
315 }
316 if (pTempTo) {
317 lenTo = strlen(pTempTo);
318 pToFile = &pTempTo[lenTo];
319// target name in target or from source
320 if (withFileName) {
321 if ((pFrom[strlen(pFrom)+1]=='\0') ||
322 (Multi && !(pTo[strlen(pTo)+1]=='\0'))) {
323 pTempFrom = pTo;
324 } else {
325// more then one source for one targetfile
326 lpFileOp->fAnyOperationsAborted=TRUE;
327 break;
328 } /* endif */
329 } else {
330 pTempFrom = pFrom;
331 } /* endif */
332// isolate target filename
333 strcpy(pToFile,pTempFrom);
334 PathRemoveFileSpecA(pToFile);
335 PathAddBackslashA(pToFile);
336 lenTo = strlen(pToFile);
337
338 strcpy(pToFile,&pTempFrom[lenTo]);
339 FromAttr = GetFileAttributesA(pFrom);
340 if (FromAttr & FILE_ATTRIBUTE_DIRECTORY) {
341 if (!(FromAttr == -1)) {
342 FIXME(__FUNCTION__" FO_COPY only with sourcedir not implemented ,stub\n");
343 };
344 lpFileOp->fAnyOperationsAborted=TRUE;
345 break;
346 }
347 ToAttr = GetFileAttributesA(pTempTo);
348 if (!(ToAttr == -1) && (ToAttr & FILE_ATTRIBUTE_DIRECTORY)) {
349 lpFileOp->fAnyOperationsAborted=TRUE;
350 break;
351 }
352// first try to copy
353 copyOk = CopyFileA(pFrom, pTempTo, not_overwrite);
354
355 if (!copyOk && not_overwrite) {
356 if (SHELL_ConfirmDialog (ASK_OVERWRITE_FILE, pTempTo))
357// second try to copy after confirm
358 copyOk = CopyFileA(pFrom, pTempTo, FALSE);
359 } /* endif */
360 if (!copyOk) lpFileOp->fAnyOperationsAborted=TRUE;
361// fix for mor then one source for one target
362 pToFile[0] = '\0';
363
364 if (!withFileName && Multi && (pTo[strlen(pTo)+1]=='\0')) {
365// Win Bug ?
366 Multi = FALSE;
367 } /* endif */
368 if (Multi) HeapFree(GetProcessHeap(), 0, pTempTo);
369 }
370
371 pFrom += strlen(pFrom) + 1;
372
373 if (Multi) pTo += strlen(pTo) + 1;
374
375 }
376 } /* endif */
377 if (!Multi && pTempTo) HeapFree(GetProcessHeap(), 0, pTempTo);
378
379 if (lpFileOp->fAnyOperationsAborted==TRUE) {
380 TRACE(__FUNCTION__" Setting AnyOpsAborted=TRUE\n");
381 return 0x75l;
382 } else {
383 TRACE(__FUNCTION__" Setting AnyOpsAborted=FALSE\n");
384 } /* endif */
385 return 0;
386#else
387 while(1) {
388 if(!pFrom[0]) break;
389 if(!pTo[0]) break;
390 TRACE(" From='%s' To='%s'\n", pFrom, pTo);
391
392 pTempTo = HeapAlloc(GetProcessHeap(), 0, strlen(pTo)+1);
393 if (pTempTo)
394 {
395 strcpy( pTempTo, pTo );
396 PathRemoveFileSpecA(pTempTo);
397 TRACE(" Creating Directory '%s'\n", pTempTo);
398 SHCreateDirectory(NULL,pTempTo);
399 HeapFree(GetProcessHeap(), 0, pTempTo);
400 }
401 CopyFileA(pFrom, pTo, FALSE);
402
403 pFrom += strlen(pFrom) + 1;
404 pTo += strlen(pTo) + 1;
405 }
406 TRACE("Setting AnyOpsAborted=FALSE\n");
407 lpFileOp->fAnyOperationsAborted=FALSE;
408 return 0;
409#endif
410
411 case FO_DELETE:
412 TRACE("File Delete:\n");
413 while(1) {
414 if(!pFrom[0]) break;
415 TRACE(" File='%s'\n", pFrom);
416 DeleteFileA(pFrom);
417 pFrom += strlen(pFrom) + 1;
418 }
419 TRACE("Setting AnyOpsAborted=FALSE\n");
420 lpFileOp->fAnyOperationsAborted=FALSE;
421 return 0;
422
423 default:
424 FIXME("Unhandled shell file operation %d\n", lpFileOp->wFunc);
425 }
426
427 return 1;
428}
429
430/*************************************************************************
431 * SHFileOperationW [SHELL32.244]
432 *
433 * NOTES
434 * exported by name
435 */
436DWORD WINAPI SHFileOperationW (LPSHFILEOPSTRUCTW lpFileOp)
437{
438 FIXME("(%p):stub.\n", lpFileOp);
439 return 1;
440}
441
442/*************************************************************************
443 * SHFileOperation [SHELL32.242]
444 *
445 */
446DWORD WINAPI SHFileOperationAW(LPVOID lpFileOp)
447{
448 if (SHELL_OsIsUnicode())
449 return SHFileOperationW(lpFileOp);
450 return SHFileOperationA(lpFileOp);
451}
452
453/*************************************************************************
454 * SheGetDirW [SHELL32.281]
455 *
456 */
457HRESULT WINAPI SheGetDirW(LPWSTR u, LPWSTR v)
458{ FIXME("%p %p stub\n",u,v);
459 return 0;
460}
461
462/*************************************************************************
463 * SheChangeDirW [SHELL32.274]
464 *
465 */
466HRESULT WINAPI SheChangeDirW(LPWSTR u)
467{ FIXME("(%s),stub\n",debugstr_w(u));
468 return 0;
469}
470
471/*************************************************************************
472 * IsNetDrive [SHELL32.66]
473 */
474BOOL WINAPI IsNetDrive(DWORD drive)
475{
476 char root[4];
477 strcpy(root, "A:\\");
478 root[0] += drive;
479 return (GetDriveTypeA(root) == DRIVE_REMOTE);
480}
Note: See TracBrowser for help on using the repository browser.