0030609: Coding - eliminate warnings issued by gcc 8.1.0
[occt.git] / src / OSD / OSD_WNT.cxx
1 // Created by: PLOTNIKOV Eugeny
2 // Copyright (c) 1996-1999 Matra Datavision
3 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifdef _WIN32
17
18 /******************************************************************************/
19 /* File:      OSD_WNT.cxx                                                     */
20 /* Purpose:   Security management routines ( more convinient than WIN32       */
21 /*            ones ) and other convinient functions.                          */
22 /******************************************************************************/
23 /***/
24 #include <OSD_WNT.hxx>
25
26 #include <strsafe.h>
27 #include <wchar.h>
28 #include <stdlib.h>
29
30 #include <Standard_Macro.hxx>
31
32 /***/
33 #ifndef OCCT_UWP
34 static void Init ( void );
35 /***/
36 class Init_OSD_WNT {  // provides initialization
37
38  public:
39
40   Init_OSD_WNT () { Init (); }
41
42 }; // end Init_OSD_WNT
43
44 static Init_OSD_WNT initOsdWnt;
45 #endif
46 /***/
47 static BOOL   fInit = FALSE;
48 static PSID*  predefinedSIDs;
49 static HANDLE hHeap;
50 /***/
51 static MOVE_DIR_PROC     _move_dir_proc;
52 static COPY_DIR_PROC     _copy_dir_proc;
53 static 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 /***/
68 #ifndef OCCT_UWP
69 // None of the existing security APIs are supported in a UWP applications
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 /***/
77 PSECURITY_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 /***/
103 void 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
134 LPVOID 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
179 leave: ;     // 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 /***/
199 void 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 /***/
214 static 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 /***/
287 BOOL 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 /***/
307 BOOL 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 /***/
341 PSID 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 /***/
352 PSID 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 /***/
364 PSID 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 /***/
376 PSID 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 /***/
387 PSID 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 /***/
399 PSID 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 /***/
411 PSID 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 /***/
422 PSID 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 /***/
433 PSID 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
457 PSECURITY_DESCRIPTOR GetFileSecurityEx ( LPCWSTR fileName, SECURITY_INFORMATION si ) {
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
472    if (  !GetFileSecurityW (
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
504 leave: ;        // 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 /***/
524 void FreeFileSecurity ( PSECURITY_DESCRIPTOR pSD ) {
525
526  HeapFree (  hHeap, 0, ( LPVOID )pSD  );
527
528 }  /* end FreeFileSecurity */
529
530
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 /***/
539 PACL 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 /***/
559 void FreeAcl ( PACL pACL ) {
560
561  HeapFree (  hHeap, 0, ( PVOID )pACL  );
562
563 }  /* end FreeAcl */
564
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 /***/
572 PVOID 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 /***/
603 void FreeAce ( PVOID pACE ) {
604
605  HeapFree ( hHeap, 0, pACE );
606
607 }  /* end FreeAce */
608 #endif
609 #define WILD_CARD     L"/*.*"
610 #define WILD_CARD_LEN (  sizeof ( WILD_CARD )  )
611
612 /***/
613 /******************************************************************************/
614 /* Function : MoveDirectory                                                 */
615 /* Purpose  : Moves specified directory tree to the new location            */
616 /* Returns  : TRUE on success, FALSE otherwise                              */
617 /******************************************************************************/
618 /***/
619 static 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       {
640 retry:
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, MAX_PATH, &anOldDirLength);
703     const size_t aNameLength = anOldDirLength + WILD_CARD_LEN + sizeof (L'\x00');
704     if ((pFD = (WIN32_FIND_DATAW* )HeapAlloc (hHeap, 0, sizeof(WIN32_FIND_DATAW))) != NULL
705      && (pName =        (wchar_t* )HeapAlloc (hHeap, 0, aNameLength)) != NULL)
706     {
707       StringCchCopyW (pName, aNameLength, oldDir);
708       StringCchCatW  (pName, aNameLength, WILD_CARD);
709       retVal = TRUE;
710       hFindFile = FindFirstFileExW (pName, FindExInfoStandard, pFD, FindExSearchNameMatch, NULL, 0);
711       for (BOOL fFind = hFindFile != INVALID_HANDLE_VALUE; fFind; fFind = FindNextFileW (hFindFile, pFD))
712       {
713         if ((pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'\0')
714          || (pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'.' && pFD->cFileName[2] == L'\0'))
715         {
716           continue;
717         }
718
719         size_t aNewDirLength = 0, aFileNameLength = 0;
720         StringCchLengthW (newDir, MAX_PATH, &aNewDirLength);
721         StringCchLengthW (pFD->cFileName, sizeof(pFD->cFileName) / sizeof(pFD->cFileName[0]), &aFileNameLength);
722         const size_t aFullNameSrcLength = anOldDirLength + aFileNameLength + sizeof (L'/') + sizeof (L'\x00');
723         const size_t aFullNameDstLength = aNewDirLength + aFileNameLength + sizeof (L'/') + sizeof (L'\x00');
724         if ((pFullNameSrc = (wchar_t* )HeapAlloc (hHeap, 0, aFullNameSrcLength)) == NULL
725           || (pFullNameDst = (wchar_t* )HeapAlloc (hHeap, 0, aFullNameDstLength)) == NULL)
726         {
727           break;
728         }
729
730         StringCchCopyW (pFullNameSrc, aFullNameSrcLength, oldDir);
731         StringCchCatW  (pFullNameSrc, aFullNameSrcLength, L"/");
732         StringCchCatW  (pFullNameSrc, aFullNameSrcLength, pFD->cFileName);
733
734         StringCchCopyW (pFullNameDst, aFullNameDstLength, newDir);
735         StringCchCatW  (pFullNameDst, aFullNameDstLength, L"/");
736         StringCchCatW  (pFullNameDst, aFullNameDstLength, pFD->cFileName);
737
738         if ((pFD->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
739         {
740           retVal = MoveDirectory (pFullNameSrc, pFullNameDst, theRecurseLevel);
741           if (!retVal)
742           {
743             break;
744           }
745         }
746         else
747         {
748 retry_1:
749           retVal = MoveFileExW (pFullNameSrc, pFullNameDst, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
750           if (!retVal)
751           {
752             if (_response_dir_proc != NULL)
753             {
754               const DIR_RESPONSE response = _response_dir_proc (pFullNameSrc);
755               if (response == DIR_ABORT)
756               {
757                 break;
758               }
759               else if (response == DIR_RETRY)
760               {
761                 goto retry_1;
762               }
763               else if (response == DIR_IGNORE)
764               {
765                 retVal = TRUE;
766               }
767               else
768               {
769                 break;
770               }
771             }
772           }
773           else if (_move_dir_proc != NULL)
774           {
775             _move_dir_proc (pFullNameSrc, pFullNameDst);
776           }
777         }
778
779         HeapFree (hHeap, 0, pFullNameDst);
780         HeapFree (hHeap, 0, pFullNameSrc);
781         pFullNameSrc = pFullNameDst = NULL;
782       }
783     }
784   }
785
786   if (hFindFile != INVALID_HANDLE_VALUE)
787   {
788     FindClose (hFindFile);
789   }
790
791   if (pFullNameSrc != NULL)
792   {
793     HeapFree (hHeap, 0, pFullNameSrc);
794   }
795   if (pFullNameDst != NULL)
796   {
797     HeapFree (hHeap, 0, pFullNameDst);
798   }
799   if (pName != NULL)
800   {
801     HeapFree (hHeap, 0, pName);
802   }
803   if (pFD != NULL)
804   {
805     HeapFree (hHeap, 0, pFD);
806   }
807
808   if (retVal)
809   {
810 retry_2:
811     retVal = RemoveDirectoryW (oldDir);
812     if (!retVal)
813     {
814       if (_response_dir_proc != NULL)
815       {
816         const DIR_RESPONSE response = _response_dir_proc (oldDir);
817         if (response == DIR_RETRY)
818         {
819           goto retry_2;
820         }
821         else if (response == DIR_IGNORE)
822         {
823           retVal = TRUE;
824         }
825       }
826     }
827   }
828
829   --theRecurseLevel;
830   return retVal;
831 }
832
833 BOOL MoveDirectory (const wchar_t* oldDir, const wchar_t* newDir)
834 {
835   DWORD aRecurseLevel = 0;
836   return MoveDirectory (oldDir, newDir, aRecurseLevel);
837 }
838
839 /***/
840 /******************************************************************************/
841 /* Function : CopyDirectory                                                 */
842 /* Purpose  : Copies specified directory tree to the new location           */
843 /* Returns  : TRUE on success, FALSE otherwise                              */
844 /******************************************************************************/
845 /***/
846 BOOL CopyDirectory (const wchar_t* dirSrc, const wchar_t* dirDst)
847 {
848   WIN32_FIND_DATAW* pFD = NULL;
849   wchar_t* pName = NULL;
850   wchar_t* pFullNameSrc = NULL;
851   wchar_t* pFullNameDst = NULL;
852   HANDLE   hFindFile = INVALID_HANDLE_VALUE;
853
854   BOOL retVal = CreateDirectoryW (dirDst, NULL);
855   if (retVal || (!retVal && GetLastError() == ERROR_ALREADY_EXISTS))
856   {
857     size_t aDirSrcLength = 0;
858     StringCchLengthW (dirSrc, MAX_PATH, &aDirSrcLength);
859     const size_t aNameLength = aDirSrcLength + WILD_CARD_LEN + sizeof (L'\x00');
860     if ((pFD = (WIN32_FIND_DATAW* )HeapAlloc (hHeap, 0, sizeof(WIN32_FIND_DATAW))) != NULL
861      && (pName = (wchar_t* )HeapAlloc (hHeap, 0, aNameLength)) != NULL)
862     {
863       StringCchCopyW(pName, aNameLength, dirSrc);
864       StringCchCatW (pName, aNameLength, WILD_CARD);
865
866       retVal = TRUE;
867       hFindFile = FindFirstFileExW (pName, FindExInfoStandard, pFD, FindExSearchNameMatch, NULL, 0);
868       for (BOOL fFind = hFindFile != INVALID_HANDLE_VALUE; fFind; fFind = FindNextFileW (hFindFile, pFD))
869       {
870         if ((pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'\0')
871          || (pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'.' && pFD->cFileName[2] == L'\0'))
872         {
873           continue;
874         }
875
876         size_t aDirDstLength = 0, aFileNameLength = 0;
877         StringCchLengthW (dirDst, MAX_PATH, &aDirDstLength);
878         StringCchLengthW (pFD->cFileName, sizeof(pFD->cFileName) / sizeof(pFD->cFileName[0]), &aFileNameLength);
879         const size_t aFullNameSrcLength = aDirSrcLength + aFileNameLength + sizeof (L'/') + sizeof (L'\x00');
880         const size_t aFullNameDstLength = aDirDstLength + aFileNameLength + sizeof (L'/') + sizeof (L'\x00');
881         if ((pFullNameSrc = (wchar_t* )HeapAlloc (hHeap, 0, aFullNameSrcLength)) == NULL
882          || (pFullNameDst = (wchar_t* )HeapAlloc (hHeap, 0, aFullNameDstLength)) == NULL)
883         {
884           break;
885         }
886
887         StringCchCopyW (pFullNameSrc, aFullNameSrcLength, dirSrc);
888         StringCchCatW  (pFullNameSrc, aFullNameSrcLength, L"/");
889         StringCchCatW  (pFullNameSrc, aFullNameSrcLength, pFD->cFileName);
890
891         StringCchCopyW (pFullNameDst, aFullNameDstLength, dirDst);
892         StringCchCatW  (pFullNameDst, aFullNameDstLength, L"/");
893         StringCchCatW  (pFullNameDst, aFullNameDstLength, pFD->cFileName);
894         if ((pFD->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
895         {
896           retVal = CopyDirectory (pFullNameSrc, pFullNameDst);
897           if (!retVal)
898           {
899             break;
900           }
901         }
902         else
903         {
904 retry:
905         #ifndef OCCT_UWP
906           retVal = CopyFileW (pFullNameSrc, pFullNameDst, FALSE);
907         #else
908           retVal = (CopyFile2 (pFullNameSrc, pFullNameDst, FALSE) == S_OK) ? TRUE : FALSE;
909         #endif
910           if (!retVal)
911           {
912             if (_response_dir_proc != NULL)
913             {
914               const DIR_RESPONSE response = _response_dir_proc (pFullNameSrc);
915               if (response == DIR_ABORT)
916               {
917                 break;
918               }
919               else if (response == DIR_RETRY)
920               {
921                 goto retry;
922               }
923               else if (response == DIR_IGNORE)
924               {
925                 retVal = TRUE;
926               }
927               else
928               {
929                 break;
930               }
931             }
932           }
933           else if (_copy_dir_proc != NULL)
934           {
935             _copy_dir_proc (pFullNameSrc, pFullNameDst);
936           }
937         }
938
939         HeapFree (hHeap, 0, pFullNameDst);
940         HeapFree (hHeap, 0, pFullNameSrc);
941         pFullNameSrc = pFullNameDst = NULL;
942       }
943     }
944   }
945
946   if (hFindFile != INVALID_HANDLE_VALUE)
947   {
948     FindClose (hFindFile);
949   }
950
951   if (pFullNameSrc != NULL)
952   {
953     HeapFree (hHeap, 0, pFullNameSrc);
954   }
955   if (pFullNameDst != NULL)
956   {
957     HeapFree (hHeap, 0, pFullNameDst);
958   }
959   if (pName != NULL)
960   {
961     HeapFree (hHeap, 0, pName);
962   }
963   if (pFD != NULL)
964   {
965     HeapFree (hHeap, 0, pFD);
966   }
967
968   return retVal;
969 }  /* end CopyDirectory */
970 /***/
971 /******************************************************************************/
972 /* Function : SetMoveDirectoryProc                                          */
973 /* Purpose  : Sets callback procedure which is calling by the               */ 
974 /*            'MoveDirectory' after moving of each item in the              */
975 /*            directory. To unregister this callback function supply NULL   */
976 /*            pointer                                                       */
977 /******************************************************************************/
978 /***/
979 void SetMoveDirectoryProc ( MOVE_DIR_PROC proc ) {
980
981  _move_dir_proc = proc;
982
983 }  /* end SetMoveDirectoryProc */
984 /***/
985 /******************************************************************************/
986 /* Function : SetCopyDirectoryProc                                          */
987 /* Purpose  : Sets callback procedure which is calling by the               */ 
988 /*            'CopyDirectory' after copying of each item in the             */
989 /*            directory. To unregister this callback function supply NULL   */
990 /*            pointer                                                       */
991 /******************************************************************************/
992 /***/
993 void SetCopyDirectoryProc ( COPY_DIR_PROC proc ) {
994
995  _copy_dir_proc = proc;
996
997 }  /* end SetCopyDirectoryProc */
998 /***/
999 /******************************************************************************/
1000 /* Function : SetResponseDirectoryProc                                      */
1001 /* Purpose  : Sets callback procedure which is calling by the               */ 
1002 /*            directoy processing function if an error was occur.           */
1003 /*            The return value of that callback procedure determines        */
1004 /*            behaviour of directoy processing functions in case of error.  */
1005 /*            To unregister this callback function supply NULL pointer      */
1006 /******************************************************************************/
1007 /***/
1008 void SetResponseDirectoryProc ( RESPONSE_DIR_PROC proc ) {
1009
1010  _response_dir_proc = proc;
1011
1012 }  /* end SetResponseDirectoryProc */
1013 /***/
1014 /******************************************************************************/
1015 /******************************************************************************/
1016 /******************************************************************************/
1017 #endif