0030775: Foundation Classes - Preserve application-defined top-level exception filter
[occt.git] / src / OSD / OSD_WNT.cxx
CommitLineData
b311480e 1// Created by: PLOTNIKOV Eugeny
2// Copyright (c) 1996-1999 Matra Datavision
973c2be1 3// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
57c28b61 16#ifdef _WIN32
7fd59977 17
7fd59977 18/******************************************************************************/
19/* File: OSD_WNT.cxx */
20/* Purpose: Security management routines ( more convinient than WIN32 */
21/* ones ) and other convinient functions. */
7fd59977 22/******************************************************************************/
23/***/
68df8478 24#include <OSD_WNT.hxx>
7fd59977 25
5fecc495 26#include <strsafe.h>
d9ff84e8 27#include <wchar.h>
7fd59977 28#include <stdlib.h>
742cc8b0 29
30#include <Standard_Macro.hxx>
31
7fd59977 32/***/
742cc8b0 33#ifndef OCCT_UWP
7fd59977 34static void Init ( void );
35/***/
7fd59977 36class Init_OSD_WNT { // provides initialization
37
38 public:
39
68299304 40 Init_OSD_WNT () { Init (); }
7fd59977 41
42}; // end Init_OSD_WNT
43
44static Init_OSD_WNT initOsdWnt;
742cc8b0 45#endif
7fd59977 46/***/
47static BOOL fInit = FALSE;
48static PSID* predefinedSIDs;
49static HANDLE hHeap;
50/***/
7fd59977 51static MOVE_DIR_PROC _move_dir_proc;
52static COPY_DIR_PROC _copy_dir_proc;
53static RESPONSE_DIR_PROC _response_dir_proc;
54/***/
55#define PREDEFINED_SIDs_COUNT 9
56#define UNIVERSAL_PREDEFINED_SIDs_COUNT 5
57/***/
58#define SID_INTERACTIVE 0
59#define SID_NETWORK 1
60#define SID_LOCAL 2
61#define SID_DIALUP 3
62#define SID_BATCH 4
63#define SID_CREATOR_OWNER 5
64#define SID_ADMIN 6
65#define SID_WORLD 7
66#define SID_NULL 8
67/***/
742cc8b0 68#ifndef OCCT_UWP
69// None of the existing security APIs are supported in a UWP applications
7fd59977 70/******************************************************************************/
71/* Function : AllocSD */
72/* Purpose : Allocates and initializes security identifier */
73/* Returns : Pointer to allocated SID on success, NULL otherwise */
74/* Warning : Allocated SID must be deallocated by 'FreeSD' function */
75/******************************************************************************/
76/***/
77PSECURITY_DESCRIPTOR AllocSD ( void ) {
78
79 PSECURITY_DESCRIPTOR retVal =
80 ( PSECURITY_DESCRIPTOR )HeapAlloc (
81 hHeap, 0, sizeof ( SECURITY_DESCRIPTOR )
82 );
83
84 if ( retVal != NULL &&
85 !InitializeSecurityDescriptor ( retVal, SECURITY_DESCRIPTOR_REVISION )
86 ) {
87
88 HeapFree ( hHeap, 0, ( PVOID )retVal );
89 retVal = NULL;
90
91 } /* end if */
92
93 return retVal;
94
95} /* end AllocSD */
96/***/
97/******************************************************************************/
98/* Function : FreeSD */
99/* Purpose : Deallocates security identifier which was allocated by the */
100/* 'AllocSD' function */
101/******************************************************************************/
102/***/
103void FreeSD ( PSECURITY_DESCRIPTOR pSD ) {
104
105 BOOL fPresent;
106 BOOL fDaclDefaulted;
107 PACL pACL;
108
109 if ( GetSecurityDescriptorDacl ( pSD, &fPresent, &pACL, &fDaclDefaulted ) &&
110 fPresent
111 )
112
113 HeapFree ( hHeap, 0, ( PVOID )pACL );
114
115 HeapFree ( hHeap, 0, ( PVOID )pSD );
116
117} /* end FreeSD */
118/***/
119/******************************************************************************/
120/* Function : GetTokenInformationEx */
121/* Purpose : Allocates and fills out access token */
122/* Returns : Pointer to the access token on success, NULL otherwise */
123/* Warning : Allocated access token must be deallocated by */
124/* 'FreeTokenInformation' function */
125/******************************************************************************/
126/***/
127
128#if defined(__CYGWIN32__) || defined(__MINGW32__)
129#define __try
130#define __finally
131#define __leave return buffer
132#endif
133
134LPVOID GetTokenInformationEx ( HANDLE hToken, TOKEN_INFORMATION_CLASS tic ) {
135
136 DWORD errVal;
137 DWORD dwSize;
138 DWORD dwSizeNeeded = 0;
139 LPVOID buffer = NULL;
140 BOOL fOK = FALSE;
141
142 __try {
143
144 do {
145
146 dwSize = dwSizeNeeded;
147 errVal = ERROR_SUCCESS;
148
149 if ( !GetTokenInformation ( hToken, tic, buffer, dwSize, &dwSizeNeeded ) ) {
150
151 if ( ( errVal = GetLastError () ) != ERROR_INSUFFICIENT_BUFFER )
152
153 __leave;
154
155 if ( ( buffer = HeapAlloc ( hHeap, 0, dwSizeNeeded ) ) == NULL )
156
157 __leave;
158
159 } /* end if */
160
161 } while ( errVal != ERROR_SUCCESS );
162
163 fOK = TRUE;
164
165 } /* end __try */
166
167 __finally {
168
169 if ( !fOK && buffer != NULL ) {
170
171 HeapFree ( hHeap, 0, buffer );
172 buffer = NULL;
173
174 } /* end if */
175
176 } /* end __finally */
177
178#ifdef VAC
179leave: ; // added for VisualAge
180#endif
181
182 return buffer;
183
184} /* end GetTokenInformationEx */
185
186#if defined(__CYGWIN32__) || defined(__MINGW32__)
187#undef __try
188#undef __finally
189#undef __leave
190#endif
191
192/***/
193/******************************************************************************/
194/* Function : FreeTokenInformation */
195/* Purpose : Deallocates access token which was allocated by the */
196/* 'GetTokenInformationEx' function */
197/******************************************************************************/
198/***/
199void FreeTokenInformation ( LPVOID lpvTkInfo ) {
200
201 HeapFree ( hHeap, 0, lpvTkInfo );
202
203} /* end FreeTokenInformation */
204/***/
205/******************************************************************************/
206/* Function : Init */
207/* Purpose : Allocates and initializes predefined security identifiers */
208/* Warning : Generates 'STATUS_NO_MEMORY' software exception if there are */
209/* insufficient of memory. This exception can be caught by using */
210/* software exception handling ( SEH ) mechanism */
211/* ( __try / __except ) */
212/******************************************************************************/
213/***/
214static void Init ( void ) {
215
216 SID_IDENTIFIER_AUTHORITY sidIDAnull = SECURITY_NULL_SID_AUTHORITY;
217 SID_IDENTIFIER_AUTHORITY sidIDAworld = SECURITY_WORLD_SID_AUTHORITY;
218 SID_IDENTIFIER_AUTHORITY sidIDANT = SECURITY_NT_AUTHORITY;
219 SID_IDENTIFIER_AUTHORITY sidIDAlocal = SECURITY_LOCAL_SID_AUTHORITY;
220 SID_IDENTIFIER_AUTHORITY sidIDAcreator = SECURITY_CREATOR_SID_AUTHORITY;
221
222 if ( !fInit ) {
223
224 predefinedSIDs = ( PSID* )HeapAlloc (
225 hHeap = GetProcessHeap (),
226 HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
227 PREDEFINED_SIDs_COUNT * sizeof ( PSID* )
228 );
229
230 AllocateAndInitializeSid (
231 &sidIDANT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
232 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_ADMIN ]
233 );
234
235 AllocateAndInitializeSid (
236 &sidIDAworld, 1, SECURITY_WORLD_RID,
237 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_WORLD ]
238 );
239
240 AllocateAndInitializeSid (
241 &sidIDANT, 1, SECURITY_INTERACTIVE_RID,
242 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_INTERACTIVE ]
243 );
244
245 AllocateAndInitializeSid (
246 &sidIDANT, 1, SECURITY_NETWORK_RID,
247 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_NETWORK ]
248 );
249
250 AllocateAndInitializeSid (
251 &sidIDAlocal, 1, SECURITY_LOCAL_RID,
252 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_LOCAL ]
253 );
254
255 AllocateAndInitializeSid (
256 &sidIDANT, 1, SECURITY_DIALUP_RID,
257 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_DIALUP ]
258 );
259
260 AllocateAndInitializeSid (
261 &sidIDANT, 1, SECURITY_BATCH_RID,
262 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_BATCH ]
263 );
264
265 AllocateAndInitializeSid (
266 &sidIDAcreator, 1, SECURITY_CREATOR_OWNER_RID,
267 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_CREATOR_OWNER ]
268 );
269
270 AllocateAndInitializeSid (
271 &sidIDAnull, 1, SECURITY_NULL_RID,
272 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_NULL ]
273 );
274
275 fInit = TRUE;
276
277 } /* end if */
278
279} /* end init */
280/***/
281/******************************************************************************/
282/* Function : PredefinedSid */
283/* Purpose : Checks whether specified SID predefined or not */
284/* Returns : TRUE if specified SID is predefined, FALSE otherwise */
285/******************************************************************************/
286/***/
287BOOL PredefinedSid ( PSID pSID ) {
288
289 int i;
290
291 for ( i = 0; i < PREDEFINED_SIDs_COUNT; ++i )
292
293 if ( EqualSid ( pSID, predefinedSIDs[ i ] ) )
294
295 return TRUE;
296
297 return FALSE;
298
299} /* end PredefinedSid */
300/***/
301/******************************************************************************/
302/* Function : NtPredefinedSid */
303/* Purpose : Checks whether specified SID universal or not */
304/* Returns : TRUE if specified SID is NOT universal, FALSE otherwise */
305/******************************************************************************/
306/***/
307BOOL NtPredefinedSid ( PSID pSID ) {
308
309 int i;
310 PSID_IDENTIFIER_AUTHORITY pTestIDA;
311 SID_IDENTIFIER_AUTHORITY ntIDA = SECURITY_NT_AUTHORITY;
312 PDWORD pdwTestSA;
313
314 for ( i = 0; i < UNIVERSAL_PREDEFINED_SIDs_COUNT; ++i )
315
316 if ( EqualSid ( pSID, predefinedSIDs[ i ] ) )
317
318 return TRUE;
319
320 pTestIDA = GetSidIdentifierAuthority ( pSID );
321
322 if ( memcmp ( pTestIDA, &ntIDA, sizeof ( SID_IDENTIFIER_AUTHORITY ) ) == 0 ) {
323
324 pdwTestSA = GetSidSubAuthority ( pSID, 0 );
325
326 if ( *pdwTestSA == SECURITY_LOGON_IDS_RID )
327
328 return TRUE;
329
330 } /* end if */
331
332 return FALSE;
333
334} /* end NtPredefinedSid */
335/***/
336/******************************************************************************/
337/* Function : AdminSid */
338/* Purpose : Returns SID of the administrative user account */
339/******************************************************************************/
340/***/
341PSID AdminSid ( void ) {
342
343 return predefinedSIDs[ SID_ADMIN ];
344
345} /* end AdminSid */
346/***/
347/******************************************************************************/
348/* Function : WorldSid */
349/* Purpose : Returns SID of group that includes all users */
350/******************************************************************************/
351/***/
352PSID WorldSid ( void ) {
353
354 return predefinedSIDs[ SID_WORLD ];
355
356} /* end WorldSid */
357/***/
358/******************************************************************************/
359/* Function : InteractiveSid */
360/* Purpose : Returns SID of group that includes all users logged on for */
361/* interactive operation */
362/******************************************************************************/
363/***/
364PSID InteractiveSid ( void ) {
365
366 return predefinedSIDs[ SID_INTERACTIVE ];
367
368} /* end InteractiveSID */
369/***/
370/******************************************************************************/
371/* Function : NetworkSid */
372/* Purpose : Returns SID of group that includes all users logged on across */
373/* a network */
374/******************************************************************************/
375/***/
376PSID NetworkSid ( void ) {
377
378 return predefinedSIDs[ SID_NETWORK ];
379
380} /* end NetworkSid */
381/***/
382/******************************************************************************/
383/* Function : LocalSid */
384/* Purpose : Returns SID of group that includes all users logged on locally*/
385/******************************************************************************/
386/***/
387PSID LocalSid ( void ) {
388
389 return predefinedSIDs[ SID_LOCAL ];
390
391} /* end LocalSid */
392/***/
393/******************************************************************************/
394/* Function : DialupSid */
395/* Purpose : Returns SID of group that includes all users logged on to */
396/* terminals using a dialup modem */
397/******************************************************************************/
398/***/
399PSID DialupSid ( void ) {
400
401 return predefinedSIDs[ SID_DIALUP ];
402
403} /* end DialupSid */
404/***/
405/******************************************************************************/
406/* Function : BatchSid */
407/* Purpose : Returns SID of group that includes all users logged on using */
408/* a batch queue facility */
409/******************************************************************************/
410/***/
411PSID BatchSid ( void ) {
412
413 return predefinedSIDs[ SID_BATCH ];
414
415} /* end BatchSid */
416/***/
417/******************************************************************************/
418/* Function : CreatorOwnerSid */
419/* Purpose : Returns SID of 'CREATOR OWNER' special group */
420/******************************************************************************/
421/***/
422PSID CreatorOwnerSid ( void ) {
423
424 return predefinedSIDs[ SID_CREATOR_OWNER ];
425
426} /* end CreatorOwnerSid */
427/***/
428/******************************************************************************/
429/* Function : NullSid */
430/* Purpose : Returns null SID */
431/******************************************************************************/
432/***/
433PSID NullSid ( void ) {
434
435 return predefinedSIDs[ SID_NULL ];
436
437} /* end NullSid */
438/***/
439/******************************************************************************/
440/* Function : GetFileSecurityEx */
441/* Purpose : Allocates a security descriptor and fills it out by security */
442/* information which belongs to the specified file */
443/* Returns : Pointer to the allocated security descriptor on success */
444/* NULL otherwise */
445/* Warning : Allocated security descriptor must be deallocated by */
446/* 'FreeFileSecurity' function */
447/******************************************************************************/
448/***/
449
450
451#if defined(__CYGWIN32__) || defined(__MINGW32__)
452#define __try
453#define __finally
454#define __leave return retVal
455#endif
456
d9ff84e8 457PSECURITY_DESCRIPTOR GetFileSecurityEx ( LPCWSTR fileName, SECURITY_INFORMATION si ) {
7fd59977 458
459 DWORD errVal;
460 DWORD dwSize;
461 DWORD dwSizeNeeded = 0;
462 PSECURITY_DESCRIPTOR retVal = NULL;
463 BOOL fOK = FALSE;
464
465 __try {
466
467 do {
468
469 dwSize = dwSizeNeeded;
470 errVal = ERROR_SUCCESS;
471
d9ff84e8 472 if ( !GetFileSecurityW (
7fd59977 473 fileName, si,
474 retVal, dwSize, &dwSizeNeeded
475 )
476 ) {
477
478 if ( ( errVal = GetLastError () ) != ERROR_INSUFFICIENT_BUFFER ) __leave;
479
480 if ( ( retVal = ( PSECURITY_DESCRIPTOR )HeapAlloc ( hHeap, 0, dwSizeNeeded )
481 ) == NULL
482 ) __leave;
483
484 } /* end if */
485
486 } while ( errVal != ERROR_SUCCESS );
487
488 fOK = TRUE;
489
490 } /* end __try */
491
492 __finally {
493
494 if ( !fOK && retVal != NULL ) {
495
496 HeapFree ( hHeap, 0, retVal );
497 retVal = NULL;
498
499 } /* end if */
500
501 } /* end __finally */
502
503#ifdef VAC
504leave: ; // added for VisualAge
505#endif
506
507 return retVal;
508
509} /* end GetFileSecurityEx */
510
511#if defined(__CYGWIN32__) || defined(__MINGW32__)
512#undef __try
513#undef __finally
514#undef __leave
515#endif
516
517/***/
518/******************************************************************************/
519/* Function : FreeFileSecurity */
520/* Purpose : Deallocates security descriptor which was allocated by the */
521/* 'GetFileSecurityEx' function */
522/******************************************************************************/
523/***/
524void FreeFileSecurity ( PSECURITY_DESCRIPTOR pSD ) {
525
526 HeapFree ( hHeap, 0, ( LPVOID )pSD );
527
528} /* end FreeFileSecurity */
7fd59977 529
7fd59977 530
7fd59977 531/******************************************************************************/
532/* Function : CreateAcl */
533/* Purpose : Allocates and initializes access-control list */
534/* Returns : Pointer to the allocated and initialized ACL on success, */
535/* NULL otherwise */
536/* Warning : Allocated ACL must be deallocated by 'FreeAcl' function */
537/******************************************************************************/
538/***/
539PACL CreateAcl ( DWORD dwAclSize ) {
540
541 PACL retVal;
542
543 retVal = ( PACL )HeapAlloc ( hHeap, 0, dwAclSize );
544
545 if ( retVal != NULL )
546
547 InitializeAcl ( retVal, dwAclSize, ACL_REVISION );
548
549 return retVal;
550
551} /* end CreateAcl */
552/***/
553/******************************************************************************/
554/* Function : FreeAcl */
555/* Purpose : Deallocates access-control list which was allocated by the */
556/* 'CreateAcl' function */
557/******************************************************************************/
558/***/
559void FreeAcl ( PACL pACL ) {
560
561 HeapFree ( hHeap, 0, ( PVOID )pACL );
562
563} /* end FreeAcl */
7fd59977 564
7fd59977 565/******************************************************************************/
566/* Function : AllocAccessAllowedAce */
567/* Purpose : Allocates and initializes access-control entry */
568/* Returns : Pointer to the ACE on success, NULL othrwise */
569/* Warning : Allocated ACE must be deallocated by the 'FreeAce' function */
570/******************************************************************************/
571/***/
572PVOID AllocAccessAllowedAce ( DWORD dwMask, BYTE flags, PSID pSID ) {
573
574 PFILE_ACE retVal;
575 WORD wSize;
576
577 wSize = (WORD)( sizeof ( ACE_HEADER ) + sizeof ( DWORD ) + GetLengthSid ( pSID ) );
578
579 retVal = ( PFILE_ACE )HeapAlloc ( hHeap, 0, wSize );
580
581 if ( retVal != NULL ) {
582
583 retVal -> header.AceType = ACCESS_ALLOWED_ACE_TYPE;
584 retVal -> header.AceFlags = flags;
585 retVal -> header.AceSize = wSize;
586
587 retVal -> dwMask = dwMask;
588
589 CopySid ( GetLengthSid ( pSID ), &retVal -> pSID, pSID );
590
591 } /* end if */
592
593 return retVal;
594
595} /* end AllocAccessAllowedAce */
596/***/
597/******************************************************************************/
598/* Function : FreeAce */
599/* Purpose : Deallocates an ACE which was allocated by the */
600/* 'AllocAccessAllowedAce ' function */
601/******************************************************************************/
602/***/
603void FreeAce ( PVOID pACE ) {
604
605 HeapFree ( hHeap, 0, pACE );
606
607} /* end FreeAce */
742cc8b0 608#endif
d9ff84e8 609#define WILD_CARD L"/*.*"
7fd59977 610#define WILD_CARD_LEN ( sizeof ( WILD_CARD ) )
611
7fd59977 612/***/
613/******************************************************************************/
614/* Function : MoveDirectory */
615/* Purpose : Moves specified directory tree to the new location */
616/* Returns : TRUE on success, FALSE otherwise */
617/******************************************************************************/
618/***/
c0f08310 619static BOOL MoveDirectory (const wchar_t* oldDir, const wchar_t* newDir, DWORD& theRecurseLevel)
620{
621 wchar_t* driveSrc = NULL;
622 wchar_t* driveDst = NULL;
623 wchar_t* pathSrc = NULL;
624 wchar_t* pathDst = NULL;
625 BOOL retVal = FALSE;
626 if (theRecurseLevel == 0)
627 {
628 ++theRecurseLevel;
629 BOOL fFind = FALSE;
630 if ((driveSrc = (wchar_t* )HeapAlloc (hHeap, 0, _MAX_DRIVE * sizeof(wchar_t))) != NULL
631 && (driveDst = (wchar_t* )HeapAlloc (hHeap, 0, _MAX_DRIVE * sizeof(wchar_t))) != NULL
632 && (pathSrc = (wchar_t* )HeapAlloc (hHeap, 0, _MAX_DIR * sizeof(wchar_t))) != NULL
633 && (pathDst = (wchar_t* )HeapAlloc (hHeap, 0, _MAX_DIR * sizeof(wchar_t))) != NULL)
634 {
635 _wsplitpath (oldDir, driveSrc, pathSrc, NULL, NULL);
636 _wsplitpath (newDir, driveDst, pathDst, NULL, NULL);
637 if (wcscmp (driveSrc, driveDst) == 0
638 && wcscmp (pathSrc, pathDst ) == 0)
639 {
640retry:
641 retVal = MoveFileExW (oldDir, newDir, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
642 fFind = TRUE;
643 if (!retVal)
644 {
645 if (_response_dir_proc != NULL)
646 {
647 const DIR_RESPONSE response = _response_dir_proc (oldDir);
648 if (response == DIR_RETRY)
649 {
650 goto retry;
651 }
652 else if (response == DIR_IGNORE)
653 {
654 retVal = TRUE;
655 }
656 }
657 }
658 else if (_move_dir_proc != NULL)
659 {
660 _move_dir_proc (oldDir, newDir);
661 }
662 }
663 }
664
665 if (pathDst != NULL)
666 {
667 HeapFree (hHeap, 0, pathDst);
668 }
669 if (pathSrc != NULL)
670 {
671 HeapFree (hHeap, 0, pathSrc);
672 }
673 if (driveDst != NULL)
674 {
675 HeapFree (hHeap, 0, driveDst);
676 }
677 if (driveSrc != NULL)
678 {
679 HeapFree (hHeap, 0, driveSrc);
680 }
681
682 if (fFind)
683 {
684 --theRecurseLevel;
685 return retVal;
686 }
687 }
688 else
689 {
690 ++theRecurseLevel;
691 }
692
693 WIN32_FIND_DATAW* pFD = NULL;
694 wchar_t* pName = NULL;
695 wchar_t* pFullNameSrc = NULL;
696 wchar_t* pFullNameDst = NULL;
697 HANDLE hFindFile = INVALID_HANDLE_VALUE;
698 retVal = CreateDirectoryW (newDir, NULL);
699 if (retVal || (!retVal && GetLastError() == ERROR_ALREADY_EXISTS))
700 {
701 size_t anOldDirLength;
702 StringCchLengthW (oldDir, sizeof(oldDir) / sizeof(oldDir[0]), &anOldDirLength);
703 if ((pFD = (WIN32_FIND_DATAW* )HeapAlloc (hHeap, 0, sizeof(WIN32_FIND_DATAW))) != NULL
704 && (pName = (wchar_t* )HeapAlloc (hHeap, 0, anOldDirLength + WILD_CARD_LEN + sizeof(L'\x00'))) != NULL)
705 {
706 StringCchCopyW (pName, sizeof(pName) / sizeof(pName[0]), oldDir);
707 StringCchCatW (pName, sizeof(pName), WILD_CARD);
708 retVal = TRUE;
709 hFindFile = FindFirstFileExW (pName, FindExInfoStandard, pFD, FindExSearchNameMatch, NULL, 0);
710 for (BOOL fFind = hFindFile != INVALID_HANDLE_VALUE; fFind; fFind = FindNextFileW (hFindFile, pFD))
711 {
712 if ((pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'\0')
713 || (pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'.' && pFD->cFileName[2] == L'\0'))
714 {
715 continue;
716 }
717
718 size_t anOldDirLength2 = 0, aNewDirLength = 0, aFileNameLength = 0;
719 StringCchLengthW (oldDir, sizeof(oldDir) / sizeof(oldDir[0]), &anOldDirLength2);
720 StringCchLengthW (newDir, sizeof(newDir) / sizeof(newDir[0]), &aNewDirLength);
721 StringCchLengthW (pFD->cFileName, sizeof(pFD->cFileName) / sizeof(pFD->cFileName[0]), &aFileNameLength);
722 if ((pFullNameSrc = (wchar_t* )HeapAlloc (hHeap, 0, anOldDirLength2 + aFileNameLength + sizeof(L'/') + sizeof(L'\x00'))) == NULL
723 || (pFullNameDst = (wchar_t* )HeapAlloc (hHeap, 0, aNewDirLength + aFileNameLength + sizeof(L'/') + sizeof(L'\x00'))) == NULL)
724 {
725 break;
726 }
727
728 StringCchCopyW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), oldDir);
729 StringCchCatW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), L"/");
730 StringCchCatW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), pFD->cFileName);
731
732 StringCchCopyW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), newDir);
733 StringCchCatW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), L"/");
734 StringCchCatW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), pFD->cFileName);
735
736 if ((pFD->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
737 {
738 retVal = MoveDirectory (pFullNameSrc, pFullNameDst, theRecurseLevel);
739 if (!retVal)
740 {
741 break;
742 }
743 }
7fd59977 744 else
c0f08310 745 {
746retry_1:
747 retVal = MoveFileExW (pFullNameSrc, pFullNameDst, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
748 if (!retVal)
749 {
750 if (_response_dir_proc != NULL)
751 {
752 const DIR_RESPONSE response = _response_dir_proc (pFullNameSrc);
753 if (response == DIR_ABORT)
754 {
755 break;
756 }
757 else if (response == DIR_RETRY)
758 {
759 goto retry_1;
760 }
761 else if (response == DIR_IGNORE)
762 {
763 retVal = TRUE;
764 }
765 else
766 {
767 break;
768 }
769 }
770 }
771 else if (_move_dir_proc != NULL)
772 {
773 _move_dir_proc (pFullNameSrc, pFullNameDst);
774 }
775 }
776
777 HeapFree (hHeap, 0, pFullNameDst);
778 HeapFree (hHeap, 0, pFullNameSrc);
779 pFullNameSrc = pFullNameDst = NULL;
780 }
781 }
782 }
783
784 if (hFindFile != INVALID_HANDLE_VALUE)
785 {
786 FindClose (hFindFile);
787 }
788
789 if (pFullNameSrc != NULL)
790 {
791 HeapFree (hHeap, 0, pFullNameSrc);
792 }
793 if (pFullNameDst != NULL)
794 {
795 HeapFree (hHeap, 0, pFullNameDst);
796 }
797 if (pName != NULL)
798 {
799 HeapFree (hHeap, 0, pName);
800 }
801 if (pFD != NULL)
802 {
803 HeapFree (hHeap, 0, pFD);
804 }
805
806 if (retVal)
807 {
808retry_2:
809 retVal = RemoveDirectoryW (oldDir);
810 if (!retVal)
811 {
812 if (_response_dir_proc != NULL)
813 {
814 const DIR_RESPONSE response = _response_dir_proc (oldDir);
815 if (response == DIR_RETRY)
816 {
817 goto retry_2;
818 }
819 else if (response == DIR_IGNORE)
820 {
821 retVal = TRUE;
822 }
823 }
824 }
825 }
826
827 --theRecurseLevel;
828 return retVal;
829}
7fd59977 830
c0f08310 831BOOL MoveDirectory (const wchar_t* oldDir, const wchar_t* newDir)
68299304 832{
833 DWORD aRecurseLevel = 0;
834 return MoveDirectory (oldDir, newDir, aRecurseLevel);
835}
836
7fd59977 837/***/
838/******************************************************************************/
839/* Function : CopyDirectory */
840/* Purpose : Copies specified directory tree to the new location */
841/* Returns : TRUE on success, FALSE otherwise */
842/******************************************************************************/
843/***/
c0f08310 844BOOL CopyDirectory (const wchar_t* dirSrc, const wchar_t* dirDst)
845{
846 WIN32_FIND_DATAW* pFD = NULL;
847 wchar_t* pName = NULL;
848 wchar_t* pFullNameSrc = NULL;
849 wchar_t* pFullNameDst = NULL;
850 HANDLE hFindFile = INVALID_HANDLE_VALUE;
851
852 BOOL retVal = CreateDirectoryW (dirDst, NULL);
853 if (retVal || (!retVal && GetLastError() == ERROR_ALREADY_EXISTS))
854 {
855 size_t aDirSrcLength = 0;
856 StringCchLengthW (dirSrc, sizeof(dirSrc) / sizeof(dirSrc[0]), &aDirSrcLength);
857 if ((pFD = (WIN32_FIND_DATAW* )HeapAlloc (hHeap, 0, sizeof(WIN32_FIND_DATAW))) != NULL
858 && (pName = (wchar_t* )HeapAlloc (hHeap, 0, aDirSrcLength + WILD_CARD_LEN + sizeof(L'\x00'))) != NULL)
859 {
860 StringCchCopyW(pName, sizeof(pName) / sizeof(pName[0]), dirSrc);
861 StringCchCatW (pName, sizeof(pName) / sizeof(pName[0]), WILD_CARD);
862
863 retVal = TRUE;
864 hFindFile = FindFirstFileExW (pName, FindExInfoStandard, pFD, FindExSearchNameMatch, NULL, 0);
865 for (BOOL fFind = hFindFile != INVALID_HANDLE_VALUE; fFind; fFind = FindNextFileW (hFindFile, pFD))
866 {
867 if ((pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'\0')
868 || (pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'.' && pFD->cFileName[2] == L'\0'))
869 {
870 continue;
871 }
872
873 size_t aDirSrcLength2 = 0, aDirDstLength = 0, aFileNameLength = 0;
874 StringCchLengthW (dirSrc, sizeof(dirSrc) / sizeof(dirSrc[0]), &aDirSrcLength2);
875 StringCchLengthW (dirDst, sizeof(dirDst) / sizeof(dirDst[0]), &aDirDstLength);
876 StringCchLengthW (pFD->cFileName, sizeof(pFD->cFileName) / sizeof(pFD->cFileName[0]), &aFileNameLength);
877 if ((pFullNameSrc = (wchar_t* )HeapAlloc (hHeap, 0, aDirSrcLength2 + aFileNameLength + sizeof(L'/') + sizeof(L'\x00'))) == NULL
878 || (pFullNameDst = (wchar_t* )HeapAlloc (hHeap, 0, aDirDstLength + aFileNameLength + sizeof(L'/') + sizeof(L'\x00'))) == NULL)
879 {
880 break;
881 }
882
883 StringCchCopyW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), dirSrc);
884 StringCchCatW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), L"/");
885 StringCchCatW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), pFD->cFileName);
886
887 StringCchCopyW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), dirDst);
888 StringCchCatW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), L"/");
889 StringCchCatW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), pFD->cFileName);
890 if ((pFD->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
891 {
892 retVal = CopyDirectory (pFullNameSrc, pFullNameDst);
893 if (!retVal)
894 {
895 break;
896 }
897 }
7fd59977 898 else
c0f08310 899 {
900retry:
901 #ifndef OCCT_UWP
902 retVal = CopyFileW (pFullNameSrc, pFullNameDst, FALSE);
903 #else
904 retVal = (CopyFile2 (pFullNameSrc, pFullNameDst, FALSE) == S_OK) ? TRUE : FALSE;
905 #endif
906 if (!retVal)
907 {
908 if (_response_dir_proc != NULL)
909 {
910 const DIR_RESPONSE response = _response_dir_proc (pFullNameSrc);
911 if (response == DIR_ABORT)
912 {
913 break;
914 }
915 else if (response == DIR_RETRY)
916 {
917 goto retry;
918 }
919 else if (response == DIR_IGNORE)
920 {
921 retVal = TRUE;
922 }
923 else
924 {
925 break;
926 }
927 }
928 }
929 else if (_copy_dir_proc != NULL)
930 {
931 _copy_dir_proc (pFullNameSrc, pFullNameDst);
932 }
933 }
934
935 HeapFree (hHeap, 0, pFullNameDst);
936 HeapFree (hHeap, 0, pFullNameSrc);
937 pFullNameSrc = pFullNameDst = NULL;
938 }
939 }
940 }
941
942 if (hFindFile != INVALID_HANDLE_VALUE)
943 {
944 FindClose (hFindFile);
945 }
946
947 if (pFullNameSrc != NULL)
948 {
949 HeapFree (hHeap, 0, pFullNameSrc);
950 }
951 if (pFullNameDst != NULL)
952 {
953 HeapFree (hHeap, 0, pFullNameDst);
954 }
955 if (pName != NULL)
956 {
957 HeapFree (hHeap, 0, pName);
958 }
959 if (pFD != NULL)
960 {
961 HeapFree (hHeap, 0, pFD);
962 }
963
964 return retVal;
7fd59977 965} /* end CopyDirectory */
966/***/
967/******************************************************************************/
7fd59977 968/* Function : SetMoveDirectoryProc */
969/* Purpose : Sets callback procedure which is calling by the */
970/* 'MoveDirectory' after moving of each item in the */
971/* directory. To unregister this callback function supply NULL */
972/* pointer */
973/******************************************************************************/
974/***/
975void SetMoveDirectoryProc ( MOVE_DIR_PROC proc ) {
976
977 _move_dir_proc = proc;
978
979} /* end SetMoveDirectoryProc */
980/***/
981/******************************************************************************/
982/* Function : SetCopyDirectoryProc */
983/* Purpose : Sets callback procedure which is calling by the */
984/* 'CopyDirectory' after copying of each item in the */
985/* directory. To unregister this callback function supply NULL */
986/* pointer */
987/******************************************************************************/
988/***/
989void SetCopyDirectoryProc ( COPY_DIR_PROC proc ) {
990
991 _copy_dir_proc = proc;
992
993} /* end SetCopyDirectoryProc */
994/***/
995/******************************************************************************/
996/* Function : SetResponseDirectoryProc */
997/* Purpose : Sets callback procedure which is calling by the */
998/* directoy processing function if an error was occur. */
999/* The return value of that callback procedure determines */
1000/* behaviour of directoy processing functions in case of error. */
1001/* To unregister this callback function supply NULL pointer */
1002/******************************************************************************/
1003/***/
1004void SetResponseDirectoryProc ( RESPONSE_DIR_PROC proc ) {
1005
1006 _response_dir_proc = proc;
1007
1008} /* end SetResponseDirectoryProc */
1009/***/
1010/******************************************************************************/
1011/******************************************************************************/
1012/******************************************************************************/
1013#endif