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