0027350: Support for Universal Windows Platform
[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_1.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 ( LPCWSTR oldDir, LPCWSTR newDir, DWORD& theRecurseLevel ) {
620
621  PWIN32_FIND_DATAW    pFD;
622  LPWSTR               pName;
623  LPWSTR               pFullNameSrc;
624  LPWSTR               pFullNameDst;
625  LPWSTR               driveSrc, driveDst;
626  LPWSTR               pathSrc,  pathDst;
627  HANDLE               hFindFile;
628  BOOL                 fFind;
629  BOOL                 retVal = FALSE;
630  DIR_RESPONSE         response;
631
632  if (theRecurseLevel == 0) {
633
634   ++theRecurseLevel;
635
636   fFind = FALSE;
637   driveSrc = driveDst = pathSrc = pathDst = NULL;
638  
639   if (   (  driveSrc = ( LPWSTR )HeapAlloc ( hHeap, 0, _MAX_DRIVE * sizeof(WCHAR) )  ) != NULL &&
640          (  driveDst = ( LPWSTR )HeapAlloc ( hHeap, 0, _MAX_DRIVE * sizeof(WCHAR) )  ) != NULL &&
641          (  pathSrc  = ( LPWSTR )HeapAlloc ( hHeap, 0, _MAX_DIR * sizeof(WCHAR)   )  ) != NULL &&
642          (  pathDst  = ( LPWSTR )HeapAlloc ( hHeap, 0, _MAX_DIR * sizeof(WCHAR)   )  ) != NULL
643   ) {
644   
645    _wsplitpath ( oldDir, driveSrc, pathSrc, NULL, NULL );
646    _wsplitpath ( newDir, driveDst, pathDst, NULL, NULL );
647
648    if (  wcscmp ( driveSrc, driveDst ) == 0 &&
649          wcscmp ( pathSrc,  pathDst  ) == 0
650    ) {
651 retry:   
652     retVal = MoveFileExW (
653               oldDir, newDir, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED
654              );
655     fFind  = TRUE;
656
657     if ( !retVal ) {
658     
659      if ( _response_dir_proc != NULL ) {
660      
661       response = ( *_response_dir_proc ) ( oldDir );
662
663       if ( response == DIR_RETRY )
664
665        goto retry;
666
667       else if ( response == DIR_IGNORE )
668
669        retVal = TRUE;
670
671      }  /* end if */
672     
673     } else if ( _move_dir_proc != NULL )
674
675      ( *_move_dir_proc ) ( oldDir, newDir );
676     
677    }  /* end if */
678   
679   }  /* end if */
680
681   if ( pathDst  != NULL ) HeapFree ( hHeap, 0, pathDst  );
682   if ( pathSrc  != NULL ) HeapFree ( hHeap, 0, pathSrc  );
683   if ( driveDst != NULL ) HeapFree ( hHeap, 0, driveDst );
684   if ( driveSrc != NULL ) HeapFree ( hHeap, 0, driveSrc );
685
686   if ( fFind ) {
687     
688    --theRecurseLevel;
689    return retVal;
690
691   }  // end if
692  
693  } else {
694  
695   ++theRecurseLevel;
696  
697  }  // end else
698
699  pFD          = NULL;
700  pName        = NULL;
701  pFullNameSrc = pFullNameDst = NULL;
702  hFindFile    = INVALID_HANDLE_VALUE;
703  retVal       = FALSE;
704
705  retVal = CreateDirectoryW ( newDir, NULL );
706
707  if (   retVal || (  !retVal && GetLastError () == ERROR_ALREADY_EXISTS  )   ) {
708   size_t anOldDirLength;
709   StringCchLengthW (oldDir, sizeof(oldDir) / sizeof(oldDir[0]), &anOldDirLength);
710   if (   (  pFD = ( PWIN32_FIND_DATAW )HeapAlloc (
711                                        hHeap, 0, sizeof ( WIN32_FIND_DATAW )
712                                       )
713          ) != NULL &&
714          (
715            pName = (LPWSTR)HeapAlloc(
716              hHeap, 0, anOldDirLength + WILD_CARD_LEN +
717              sizeof(L'\x00')
718            )
719          ) != NULL
720   ) {
721     StringCchCopyW (pName, sizeof(pName) / sizeof(pName[0]), oldDir);
722     StringCchCatW  (pName, sizeof(pName), WILD_CARD);
723
724    retVal = TRUE;
725    fFind  = (  hFindFile = FindFirstFileExW(pName, FindExInfoStandard, pFD, FindExSearchNameMatch, NULL, 0)  ) != INVALID_HANDLE_VALUE;
726
727    while ( fFind ) {
728   
729     if (  pFD -> cFileName[ 0 ] != L'.' ||
730           pFD -> cFileName[ 0 ] != L'.' &&
731           pFD -> cFileName[ 1 ] != L'.'
732     ) {
733      size_t anOldDirLength2;
734      size_t aNewDirLength;
735      size_t aFileNameLength;
736
737      StringCchLengthW (oldDir, sizeof(oldDir) / sizeof(oldDir[0]), &anOldDirLength2);
738      StringCchLengthW (newDir, sizeof(newDir) / sizeof(newDir[0]), &aNewDirLength);
739      StringCchLengthW (pFD->cFileName, sizeof(pFD->cFileName) / sizeof(pFD->cFileName[0]), &aFileNameLength);
740
741      if (    (pFullNameSrc = (LPWSTR)HeapAlloc(
742                                   hHeap, 0,
743                                   anOldDirLength2 + aFileNameLength +
744                                   sizeof(L'/') + sizeof(L'\x00')
745                                  )
746              ) == NULL ||
747              (pFullNameDst = (LPWSTR)HeapAlloc(
748                                       hHeap, 0,
749                                       aNewDirLength + aFileNameLength +
750                                       sizeof(L'/') + sizeof(L'\x00')
751                                  )
752              ) == NULL
753      ) break;
754
755      StringCchCopyW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), oldDir);
756      StringCchCatW  (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), L"/");
757      StringCchCatW  (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), pFD->cFileName);
758
759      StringCchCopyW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), newDir);
760      StringCchCatW  (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), L"/");
761      StringCchCatW  (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), pFD->cFileName);
762
763      if ( pFD -> dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
764
765        retVal = MoveDirectory ( pFullNameSrc, pFullNameDst, theRecurseLevel );
766        if (!retVal) break;
767    
768      } else {
769 retry_1:   
770       retVal = MoveFileExW (pFullNameSrc, pFullNameDst,
771                             MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
772       if (! retVal) {
773       
774        if ( _response_dir_proc != NULL ) {
775       
776         response = ( *_response_dir_proc ) ( pFullNameSrc );
777
778         if ( response == DIR_ABORT )
779
780          break;
781
782         else if ( response == DIR_RETRY )
783
784          goto retry_1;
785
786         else if ( response == DIR_IGNORE )
787
788          retVal = TRUE;
789
790         else
791
792          break;
793
794        }  /* end if */
795       
796       } else if ( _move_dir_proc != NULL )
797
798        ( *_move_dir_proc ) ( pFullNameSrc, pFullNameDst );
799
800      }  /* end else */
801
802      HeapFree ( hHeap, 0, pFullNameDst );
803      HeapFree ( hHeap, 0, pFullNameSrc );
804      pFullNameSrc = pFullNameDst = NULL;
805
806     }  /* end if */
807
808     fFind = FindNextFileW ( hFindFile, pFD );
809
810    }  /* end while */
811
812   }  /* end if */
813
814  }  /* end if ( error creating directory ) */
815
816  if ( hFindFile != INVALID_HANDLE_VALUE ) FindClose ( hFindFile );
817
818  if ( pFullNameSrc != NULL ) HeapFree ( hHeap, 0, pFullNameSrc );
819  if ( pFullNameDst != NULL ) HeapFree ( hHeap, 0, pFullNameDst );
820  if ( pName        != NULL ) HeapFree ( hHeap, 0, pName        );
821  if ( pFD          != NULL ) HeapFree ( hHeap, 0, pFD          );
822
823  if ( retVal ) {
824 retry_2:  
825   retVal = RemoveDirectoryW ( oldDir );
826
827   if ( !retVal ) {
828   
829    if ( _response_dir_proc != NULL ) {
830       
831     response = ( *_response_dir_proc ) ( oldDir );
832
833     if ( response == DIR_RETRY )
834
835      goto retry_2;
836
837     else if ( response == DIR_IGNORE )
838
839      retVal = TRUE;
840
841    }  /* end if */
842
843   }  /* end if */
844   
845  }  /* end if */
846
847  --theRecurseLevel;
848
849  return retVal;
850
851 }  /* end MoveDirectory */
852
853 BOOL MoveDirectory (LPCWSTR oldDir, LPCWSTR newDir)
854 {
855   DWORD aRecurseLevel = 0;
856   return MoveDirectory (oldDir, newDir, aRecurseLevel);
857 }
858
859 /***/
860 /******************************************************************************/
861 /* Function : CopyDirectory                                                 */
862 /* Purpose  : Copies specified directory tree to the new location           */
863 /* Returns  : TRUE on success, FALSE otherwise                              */
864 /******************************************************************************/
865 /***/
866 BOOL CopyDirectory ( LPCWSTR dirSrc, LPCWSTR dirDst ) {
867
868  PWIN32_FIND_DATAW    pFD = NULL;
869  LPWSTR               pName = NULL;
870  LPWSTR               pFullNameSrc = NULL;
871  LPWSTR               pFullNameDst = NULL;
872  HANDLE               hFindFile = INVALID_HANDLE_VALUE;
873  BOOL                 fFind;
874  BOOL                 retVal = FALSE;
875  DIR_RESPONSE         response;
876
877  retVal = CreateDirectoryW ( dirDst, NULL );
878
879  if (   retVal || (  !retVal && GetLastError () == ERROR_ALREADY_EXISTS  )   ) {
880
881    size_t aDirSrcLength;
882    StringCchLengthW (dirSrc, sizeof(dirSrc) / sizeof(dirSrc[0]), &aDirSrcLength);
883
884   if (   (  pFD = ( PWIN32_FIND_DATAW )HeapAlloc (
885                                        hHeap, 0, sizeof ( WIN32_FIND_DATAW )
886                                       )
887          ) != NULL &&
888          (  pName = ( LPWSTR )HeapAlloc (
889                                hHeap, 0, aDirSrcLength + WILD_CARD_LEN +
890                                sizeof (  L'\x00'  )
891                               )
892          ) != NULL
893   ) {
894    StringCchCopyW (pName, sizeof(pName) / sizeof(pName[0]), dirSrc);
895    StringCchCatW (pName, sizeof(pName) / sizeof(pName[0]), WILD_CARD);
896
897    retVal = TRUE;
898    fFind = (hFindFile = FindFirstFileExW(pName, FindExInfoStandard, pFD, FindExSearchNameMatch, NULL, 0)) != INVALID_HANDLE_VALUE;
899
900    while ( fFind ) {
901   
902     if (  pFD -> cFileName[ 0 ] != L'.' ||
903           pFD -> cFileName[ 0 ] != L'.' &&
904           pFD -> cFileName[ 1 ] != L'.'
905     ) {
906       size_t aDirSrcLength2;
907       size_t aDirDstLength;
908       size_t aFileNameLength;
909
910       StringCchLengthW (dirSrc, sizeof(dirSrc) / sizeof(dirSrc[0]), &aDirSrcLength2);
911       StringCchLengthW (dirDst, sizeof(dirDst) / sizeof(dirDst[0]), &aDirDstLength);
912       StringCchLengthW (pFD -> cFileName, sizeof(pFD -> cFileName) / sizeof(pFD -> cFileName[0]), &aFileNameLength);
913
914      if (   ( pFullNameSrc = ( LPWSTR )HeapAlloc (
915                                         hHeap, 0,
916                                         aDirSrcLength2 + aFileNameLength +
917                                         sizeof (  L'/'  ) + sizeof (  L'\x00'  )
918                                        )
919             ) == NULL ||
920             ( pFullNameDst = ( LPWSTR )HeapAlloc (
921                                         hHeap, 0,
922                                         aDirDstLength + aFileNameLength +
923                                         sizeof (  L'/'  ) + sizeof (  L'\x00'  )
924                                        )
925             ) == NULL
926      ) break;
927   
928
929      StringCchCopyW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), dirSrc);
930      StringCchCatW  (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), L"/");
931      StringCchCatW  (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), pFD->cFileName);
932
933      StringCchCopyW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), dirDst);
934      StringCchCatW  (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), L"/");
935      StringCchCatW  (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), pFD->cFileName);
936
937      if ( pFD -> dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
938
939        retVal = CopyDirectory ( pFullNameSrc, pFullNameDst );
940        if ( ! retVal ) break;
941    
942      } else {
943 retry:   
944 #ifndef OCCT_UWP
945       retVal = CopyFileW(pFullNameSrc, pFullNameDst, FALSE);
946 #else
947       retVal = (CopyFile2(pFullNameSrc, pFullNameDst, FALSE) == S_OK) ? TRUE : FALSE;
948 #endif
949       if ( ! retVal ) {
950       
951        if ( _response_dir_proc != NULL ) {
952       
953         response = ( *_response_dir_proc ) ( pFullNameSrc );
954
955         if ( response == DIR_ABORT )
956
957          break;
958
959         else if ( response == DIR_RETRY )
960
961          goto retry;
962
963         else if ( response == DIR_IGNORE )
964
965          retVal = TRUE;
966
967         else
968
969          break;
970
971        }  /* end if */
972       
973       } else if ( _copy_dir_proc != NULL )
974
975        ( *_copy_dir_proc ) ( pFullNameSrc, pFullNameDst );
976
977      }  /* end else */
978
979      HeapFree ( hHeap, 0, pFullNameDst );
980      HeapFree ( hHeap, 0, pFullNameSrc );
981      pFullNameSrc = pFullNameDst = NULL;
982
983     }  /* end if */
984
985     fFind = FindNextFileW ( hFindFile, pFD );
986
987    }  /* end while */
988
989   }  /* end if */
990
991  }  /* end if ( error creating directory ) */
992
993  if ( hFindFile != INVALID_HANDLE_VALUE ) FindClose ( hFindFile );
994
995  if ( pFullNameSrc != NULL ) HeapFree ( hHeap, 0, pFullNameSrc );
996  if ( pFullNameDst != NULL ) HeapFree ( hHeap, 0, pFullNameDst );
997  if ( pName        != NULL ) HeapFree ( hHeap, 0, pName        );
998  if ( pFD          != NULL ) HeapFree ( hHeap, 0, pFD          );
999
1000  return retVal;
1001
1002 }  /* end CopyDirectory */
1003 /***/
1004 /******************************************************************************/
1005 /* Function : SetMoveDirectoryProc                                          */
1006 /* Purpose  : Sets callback procedure which is calling by the               */ 
1007 /*            'MoveDirectory' after moving of each item in the              */
1008 /*            directory. To unregister this callback function supply NULL   */
1009 /*            pointer                                                       */
1010 /******************************************************************************/
1011 /***/
1012 void SetMoveDirectoryProc ( MOVE_DIR_PROC proc ) {
1013
1014  _move_dir_proc = proc;
1015
1016 }  /* end SetMoveDirectoryProc */
1017 /***/
1018 /******************************************************************************/
1019 /* Function : SetCopyDirectoryProc                                          */
1020 /* Purpose  : Sets callback procedure which is calling by the               */ 
1021 /*            'CopyDirectory' after copying of each item in the             */
1022 /*            directory. To unregister this callback function supply NULL   */
1023 /*            pointer                                                       */
1024 /******************************************************************************/
1025 /***/
1026 void SetCopyDirectoryProc ( COPY_DIR_PROC proc ) {
1027
1028  _copy_dir_proc = proc;
1029
1030 }  /* end SetCopyDirectoryProc */
1031 /***/
1032 /******************************************************************************/
1033 /* Function : SetResponseDirectoryProc                                      */
1034 /* Purpose  : Sets callback procedure which is calling by the               */ 
1035 /*            directoy processing function if an error was occur.           */
1036 /*            The return value of that callback procedure determines        */
1037 /*            behaviour of directoy processing functions in case of error.  */
1038 /*            To unregister this callback function supply NULL pointer      */
1039 /******************************************************************************/
1040 /***/
1041 void SetResponseDirectoryProc ( RESPONSE_DIR_PROC proc ) {
1042
1043  _response_dir_proc = proc;
1044
1045 }  /* end SetResponseDirectoryProc */
1046 /***/
1047 /******************************************************************************/
1048 /******************************************************************************/
1049 /******************************************************************************/
1050 #endif