06b9b23f38eb219e8aff6860a2b5d8d27cdff61d
[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 static DWORD dwLevel;
32 /***/
33 class Init_OSD_WNT {  // provides initialization
34
35  public:
36
37   Init_OSD_WNT () { Init (); dwLevel = TlsAlloc (); }
38
39 }; // end Init_OSD_WNT
40
41 static Init_OSD_WNT initOsdWnt;
42 /***/
43 static BOOL   fInit = FALSE;
44 static PSID*  predefinedSIDs;
45 static HANDLE hHeap;
46 /***/
47 static MOVE_DIR_PROC     _move_dir_proc;
48 static COPY_DIR_PROC     _copy_dir_proc;
49 static RESPONSE_DIR_PROC _response_dir_proc;
50 /***/
51 #define PREDEFINED_SIDs_COUNT           9
52 #define UNIVERSAL_PREDEFINED_SIDs_COUNT 5
53 /***/
54 #define SID_INTERACTIVE   0
55 #define SID_NETWORK       1
56 #define SID_LOCAL         2
57 #define SID_DIALUP        3
58 #define SID_BATCH         4
59 #define SID_CREATOR_OWNER 5
60 #define SID_ADMIN         6
61 #define SID_WORLD         7
62 #define SID_NULL          8
63 /***/
64 /******************************************************************************/
65 /* Function : AllocSD                                                       */
66 /* Purpose  : Allocates and initializes security identifier                 */
67 /* Returns  : Pointer to allocated SID on success, NULL otherwise           */
68 /* Warning  : Allocated SID must be deallocated by 'FreeSD' function        */
69 /******************************************************************************/
70 /***/
71 PSECURITY_DESCRIPTOR AllocSD ( void ) {
72
73  PSECURITY_DESCRIPTOR retVal =
74   ( PSECURITY_DESCRIPTOR )HeapAlloc (
75                            hHeap, 0, sizeof ( SECURITY_DESCRIPTOR )
76                           );
77
78  if ( retVal != NULL &&
79       !InitializeSecurityDescriptor ( retVal, SECURITY_DESCRIPTOR_REVISION )
80  ) {
81  
82   HeapFree (  hHeap, 0, ( PVOID )retVal  );
83   retVal = NULL;
84  
85  }  /* end if */
86
87  return retVal; 
88
89 }  /* end AllocSD */
90 /***/
91 /******************************************************************************/
92 /* Function : FreeSD                                                        */
93 /* Purpose  : Deallocates security identifier which was allocated by the    */
94 /*            'AllocSD' function                                            */
95 /******************************************************************************/
96 /***/
97 void FreeSD ( PSECURITY_DESCRIPTOR pSD ) {
98
99  BOOL   fPresent;
100  BOOL   fDaclDefaulted;
101  PACL   pACL;
102  
103  if (  GetSecurityDescriptorDacl ( pSD, &fPresent, &pACL, &fDaclDefaulted ) &&
104        fPresent
105  )
106
107   HeapFree (  hHeap, 0, ( PVOID )pACL  );
108
109  HeapFree (  hHeap, 0, ( PVOID )pSD  );
110
111 }  /* end FreeSD */
112 /***/
113 /******************************************************************************/
114 /* Function : GetTokenInformationEx                                         */
115 /* Purpose  : Allocates and fills out access token                          */
116 /* Returns  : Pointer to the access token on success, NULL otherwise        */
117 /* Warning  : Allocated access token  must be deallocated by                */
118 /*            'FreeTokenInformation' function                               */
119 /******************************************************************************/
120 /***/
121
122 #if defined(__CYGWIN32__) || defined(__MINGW32__)
123 #define __try
124 #define __finally
125 #define __leave return buffer
126 #endif
127
128 LPVOID GetTokenInformationEx ( HANDLE hToken, TOKEN_INFORMATION_CLASS tic ) {
129
130  DWORD  errVal;
131  DWORD  dwSize;
132  DWORD  dwSizeNeeded = 0;
133  LPVOID buffer       = NULL;
134  BOOL   fOK          = FALSE;
135
136  __try {
137
138   do {
139
140    dwSize = dwSizeNeeded;
141    errVal = ERROR_SUCCESS;
142  
143    if (  !GetTokenInformation ( hToken, tic, buffer, dwSize, &dwSizeNeeded )  ) {
144
145     if (   (  errVal = GetLastError ()  ) != ERROR_INSUFFICIENT_BUFFER   )
146         
147      __leave;
148
149     if (  ( buffer = HeapAlloc (  hHeap, 0, dwSizeNeeded  ) ) == NULL  )
150
151      __leave;
152
153    }  /* end if */
154  
155   } while ( errVal != ERROR_SUCCESS );
156
157   fOK = TRUE;
158
159  }  /* end __try */
160
161  __finally {
162  
163   if ( !fOK && buffer != NULL ) {
164   
165    HeapFree ( hHeap, 0, buffer );
166    buffer = NULL;
167   
168   }  /* end if */
169  
170  }  /* end __finally */
171
172 #ifdef VAC
173 leave: ;     // added for VisualAge
174 #endif
175
176  return buffer;
177
178 }  /* end GetTokenInformationEx */
179
180 #if defined(__CYGWIN32__) || defined(__MINGW32__)
181 #undef __try
182 #undef __finally
183 #undef __leave
184 #endif
185
186 /***/
187 /******************************************************************************/
188 /* Function : FreeTokenInformation                                          */
189 /* Purpose  : Deallocates access token which was allocated by the           */
190 /*            'GetTokenInformationEx' function                              */
191 /******************************************************************************/
192 /***/
193 void FreeTokenInformation ( LPVOID lpvTkInfo ) {
194
195  HeapFree (  hHeap, 0, lpvTkInfo  );
196
197 }  /* end FreeTokenInformation */
198 /***/
199 /******************************************************************************/
200 /* Function : Init                                                          */
201 /* Purpose  : Allocates and initializes predefined security identifiers     */
202 /* Warning  : Generates 'STATUS_NO_MEMORY' software exception if there are  */
203 /*            insufficient of memory. This exception can be caught by using */
204 /*            software exception handling ( SEH ) mechanism                 */
205 /*            ( __try / __except )                                          */
206 /******************************************************************************/
207 /***/
208 static void Init ( void ) {
209
210  SID_IDENTIFIER_AUTHORITY sidIDAnull    = SECURITY_NULL_SID_AUTHORITY;
211  SID_IDENTIFIER_AUTHORITY sidIDAworld   = SECURITY_WORLD_SID_AUTHORITY;
212  SID_IDENTIFIER_AUTHORITY sidIDANT      = SECURITY_NT_AUTHORITY;
213  SID_IDENTIFIER_AUTHORITY sidIDAlocal   = SECURITY_LOCAL_SID_AUTHORITY;
214  SID_IDENTIFIER_AUTHORITY sidIDAcreator = SECURITY_CREATOR_SID_AUTHORITY;
215
216  if ( !fInit ) {
217
218   predefinedSIDs = ( PSID* )HeapAlloc (
219                              hHeap = GetProcessHeap (),
220                              HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
221                              PREDEFINED_SIDs_COUNT * sizeof ( PSID* )
222                             );
223
224   AllocateAndInitializeSid (
225    &sidIDANT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
226    0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_ADMIN ]
227   );
228
229   AllocateAndInitializeSid (
230    &sidIDAworld, 1, SECURITY_WORLD_RID,
231    0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_WORLD ]
232   );
233
234   AllocateAndInitializeSid (
235    &sidIDANT, 1, SECURITY_INTERACTIVE_RID,
236    0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_INTERACTIVE ]
237   );
238
239   AllocateAndInitializeSid (
240    &sidIDANT, 1, SECURITY_NETWORK_RID,
241    0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_NETWORK ]
242   );
243
244   AllocateAndInitializeSid (
245    &sidIDAlocal, 1, SECURITY_LOCAL_RID,
246    0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_LOCAL ]
247   );
248
249   AllocateAndInitializeSid (
250    &sidIDANT, 1, SECURITY_DIALUP_RID,
251    0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_DIALUP ]
252   );
253
254   AllocateAndInitializeSid (
255    &sidIDANT, 1, SECURITY_BATCH_RID,
256    0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_BATCH ]
257   );
258
259   AllocateAndInitializeSid (
260    &sidIDAcreator, 1, SECURITY_CREATOR_OWNER_RID,
261    0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_CREATOR_OWNER ]
262   );
263
264   AllocateAndInitializeSid (
265    &sidIDAnull, 1, SECURITY_NULL_RID,
266    0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_NULL ]
267   );
268
269   fInit = TRUE;
270
271  }  /* end if */
272
273 }  /* end init */
274 /***/
275 /******************************************************************************/
276 /* Function : PredefinedSid                                                 */
277 /* Purpose  : Checks whether specified SID predefined or not                */
278 /* Returns  : TRUE if specified SID is predefined, FALSE otherwise          */
279 /******************************************************************************/
280 /***/
281 BOOL PredefinedSid ( PSID pSID ) {
282
283  int i;
284
285  for ( i = 0; i < PREDEFINED_SIDs_COUNT; ++i )
286  
287   if (  EqualSid ( pSID, predefinedSIDs[ i ] )  )
288
289    return TRUE;
290  
291  return FALSE;
292
293 }  /* end PredefinedSid */
294 /***/
295 /******************************************************************************/
296 /* Function : NtPredefinedSid                                               */
297 /* Purpose  : Checks whether specified SID universal or not                 */
298 /* Returns  : TRUE if specified SID is NOT universal, FALSE otherwise       */
299 /******************************************************************************/
300 /***/
301 BOOL NtPredefinedSid ( PSID pSID ) {
302
303  int                       i;
304  PSID_IDENTIFIER_AUTHORITY pTestIDA;
305  SID_IDENTIFIER_AUTHORITY  ntIDA = SECURITY_NT_AUTHORITY;
306  PDWORD                    pdwTestSA;
307
308  for ( i = 0; i < UNIVERSAL_PREDEFINED_SIDs_COUNT; ++i )
309
310   if (  EqualSid ( pSID, predefinedSIDs[ i ] )  )
311
312    return TRUE;
313
314  pTestIDA = GetSidIdentifierAuthority ( pSID );
315
316  if (   memcmp (  pTestIDA, &ntIDA, sizeof ( SID_IDENTIFIER_AUTHORITY )  ) == 0   ) {
317  
318   pdwTestSA = GetSidSubAuthority ( pSID, 0 );
319
320   if ( *pdwTestSA == SECURITY_LOGON_IDS_RID )
321
322    return TRUE;
323      
324  }  /* end if */
325
326  return FALSE;
327
328 }  /* end NtPredefinedSid */
329 /***/
330 /******************************************************************************/
331 /* Function : AdminSid                                                      */
332 /* Purpose  : Returns SID of the administrative user account                */
333 /******************************************************************************/
334 /***/
335 PSID AdminSid ( void ) {
336
337  return predefinedSIDs[ SID_ADMIN ];
338
339 }  /* end AdminSid */
340 /***/
341 /******************************************************************************/
342 /* Function : WorldSid                                                      */
343 /* Purpose  : Returns SID of group that includes all users                  */
344 /******************************************************************************/
345 /***/
346 PSID WorldSid ( void ) {
347
348  return predefinedSIDs[ SID_WORLD ];
349
350 }  /* end WorldSid */
351 /***/
352 /******************************************************************************/
353 /* Function : InteractiveSid                                                */
354 /* Purpose  : Returns SID of group that includes all users logged on for    */
355 /*            interactive operation                                         */
356 /******************************************************************************/
357 /***/
358 PSID InteractiveSid ( void ) {
359
360  return predefinedSIDs[ SID_INTERACTIVE ];
361
362 }  /* end InteractiveSID */
363 /***/
364 /******************************************************************************/
365 /* Function : NetworkSid                                                    */
366 /* Purpose  : Returns SID of group that includes all users logged on across */
367 /*            a network                                                     */
368 /******************************************************************************/
369 /***/
370 PSID NetworkSid ( void ) {
371
372  return predefinedSIDs[ SID_NETWORK ];
373
374 }  /* end NetworkSid */
375 /***/
376 /******************************************************************************/
377 /* Function : LocalSid                                                      */
378 /* Purpose  : Returns SID of group that includes all users logged on locally*/
379 /******************************************************************************/
380 /***/
381 PSID LocalSid ( void ) {
382
383  return predefinedSIDs[ SID_LOCAL ];
384
385 }  /* end LocalSid */
386 /***/
387 /******************************************************************************/
388 /* Function : DialupSid                                                     */
389 /* Purpose  : Returns SID of group that includes all users logged on to     */
390 /*            terminals using a dialup modem                                */
391 /******************************************************************************/
392 /***/
393 PSID DialupSid ( void ) {
394
395  return predefinedSIDs[ SID_DIALUP ];
396           
397 }  /* end DialupSid */
398 /***/
399 /******************************************************************************/
400 /* Function : BatchSid                                                      */
401 /* Purpose  : Returns SID of group that includes all users logged on using  */
402 /*            a batch queue facility                                        */
403 /******************************************************************************/
404 /***/
405 PSID BatchSid ( void ) {
406
407  return predefinedSIDs[ SID_BATCH ];
408
409 }  /* end BatchSid */
410 /***/
411 /******************************************************************************/
412 /* Function : CreatorOwnerSid                                               */
413 /* Purpose  : Returns SID of 'CREATOR OWNER' special group                  */
414 /******************************************************************************/
415 /***/
416 PSID CreatorOwnerSid ( void ) {
417
418  return predefinedSIDs[ SID_CREATOR_OWNER ];
419
420 }  /* end CreatorOwnerSid */
421 /***/
422 /******************************************************************************/
423 /* Function : NullSid                                                       */
424 /* Purpose  : Returns null SID                                              */
425 /******************************************************************************/
426 /***/
427 PSID NullSid ( void ) {
428
429  return predefinedSIDs[ SID_NULL ];
430
431 }  /* end NullSid */
432 /***/
433 /******************************************************************************/
434 /* Function : GetFileSecurityEx                                             */
435 /* Purpose  : Allocates a security descriptor and fills it out by security  */
436 /*            information which belongs to the specified file               */
437 /* Returns  : Pointer to the allocated security descriptor on success       */
438 /*            NULL otherwise                                                */
439 /* Warning  : Allocated security descriptor must be deallocated by          */
440 /*            'FreeFileSecurity' function                                   */
441 /******************************************************************************/
442 /***/
443
444
445 #if defined(__CYGWIN32__) || defined(__MINGW32__)
446 #define __try
447 #define __finally
448 #define __leave return retVal
449 #endif
450
451 PSECURITY_DESCRIPTOR GetFileSecurityEx ( LPCWSTR fileName, SECURITY_INFORMATION si ) {
452
453  DWORD                errVal;
454  DWORD                dwSize;
455  DWORD                dwSizeNeeded = 0;
456  PSECURITY_DESCRIPTOR retVal = NULL;
457  BOOL                 fOK    = FALSE;
458
459  __try {
460
461   do {
462
463    dwSize = dwSizeNeeded;
464    errVal = ERROR_SUCCESS;
465
466    if (  !GetFileSecurityW (
467            fileName, si,
468            retVal, dwSize, &dwSizeNeeded
469           )
470    ) {
471  
472     if (   (  errVal = GetLastError ()  ) != ERROR_INSUFFICIENT_BUFFER   ) __leave;
473
474     if (   (  retVal = ( PSECURITY_DESCRIPTOR )HeapAlloc ( hHeap, 0, dwSizeNeeded )
475            ) == NULL
476     ) __leave;
477
478    }  /* end if */
479  
480   } while ( errVal != ERROR_SUCCESS );
481
482   fOK = TRUE;
483
484  }  /* end __try */
485
486  __finally {
487  
488   if ( !fOK && retVal != NULL ) {
489   
490    HeapFree ( hHeap, 0, retVal );
491    retVal = NULL;
492   
493   }  /* end if */
494  
495  }  /* end __finally */
496
497 #ifdef VAC
498 leave: ;        // added for VisualAge
499 #endif
500
501  return retVal;
502
503 }  /* end GetFileSecurityEx */
504
505 #if defined(__CYGWIN32__) || defined(__MINGW32__)
506 #undef __try
507 #undef __finally
508 #undef __leave
509 #endif
510
511 /***/
512 /******************************************************************************/
513 /* Function : FreeFileSecurity                                              */
514 /* Purpose  : Deallocates security descriptor which was allocated by the    */
515 /*            'GetFileSecurityEx' function                                  */
516 /******************************************************************************/
517 /***/
518 void FreeFileSecurity ( PSECURITY_DESCRIPTOR pSD ) {
519
520  HeapFree (  hHeap, 0, ( LPVOID )pSD  );
521
522 }  /* end FreeFileSecurity */
523 /***/
524 /******************************************************************************/
525 /* Function : LookupAccountSidEx                                            */
526 /* Purpose  : Looking for account corresponding to the given SID and returns*/
527 /*            a name of that account on success                             */
528 /* Returns  : TRUE if account was found in the security database            */
529 /*            FALSE otherwise                                               */
530 /* Warning  : If account was found then this function allocates memory      */
531 /*            needed to hold the name of that account and the name of the   */
532 /*            domain to which this account belongs. To free that memoty     */
533 /*            use 'FreeAccountNames' function                               */
534 /******************************************************************************/
535 /***/
536
537 #if defined(__CYGWIN32__) || defined(__MINGW32__)
538 #define __try
539 #define __finally
540 #define __leave return retVal
541 #endif
542
543 BOOL LookupAccountSidEx ( PSID pSID, LPWSTR* name, LPWSTR* domain ) {
544
545  DWORD        errVal;
546  DWORD        dwSizeName   = 0;
547  DWORD        dwSizeDomain = 0;
548  BOOL         retVal       = FALSE;
549  SID_NAME_USE eUse;
550
551  __try {
552
553   do {   
554
555    errVal = ERROR_SUCCESS;
556
557    if (  !LookupAccountSidW (
558            NULL, pSID, *name, &dwSizeName, *domain, &dwSizeDomain, &eUse
559           )
560    ) {
561    
562     if (   (  errVal = GetLastError ()  ) != ERROR_INSUFFICIENT_BUFFER   ) __leave;
563
564     if (   (  *name   = ( LPWSTR )HeapAlloc ( hHeap, 0, dwSizeName   )  ) == NULL ||
565            (  *domain = ( LPWSTR )HeapAlloc ( hHeap, 0, dwSizeDomain )  ) == NULL
566     ) __leave;
567    
568    }  /* end if */
569
570   } while ( errVal != ERROR_SUCCESS );
571
572   retVal = TRUE;
573  
574  }  /* end __try */
575
576  __finally {
577
578   if ( !retVal ) {
579   
580    if ( *name   == NULL ) HeapFree ( hHeap, 0, *name   );
581    if ( *domain == NULL ) HeapFree ( hHeap, 0, *domain );
582   
583   }  /* end if */
584  
585  }  /* end __finally */
586
587 #ifdef VAC
588 leave: ;        // added for VisualAge
589 #endif
590
591  return retVal;
592
593 }  /* end LookupAccountSidEx */
594
595 #if defined(__CYGWIN32__) || defined(__MINGW32__)
596 #undef __try
597 #undef __finally
598 #undef __leave
599 #endif
600
601 /***/
602 /******************************************************************************/
603 /* Function : FreeAccountNames                                              */
604 /* Purpose  : Deallocates memory which was allocated by the                 */
605 /*            'LookupAccountSidEx' function                                 */
606 /******************************************************************************/
607 /***/
608 void FreeAccountNames ( LPWSTR lpszName, LPWSTR lpszDomain ) {
609
610  HeapFree (  hHeap, 0, ( PVOID )lpszDomain  );
611  HeapFree (  hHeap, 0, ( PVOID )lpszName    );
612
613 }  /* end FreeAccountNames */
614 /***/
615 /******************************************************************************/
616 /* Function : GetSecurityDescriptorOwnerEx                                  */
617 /* Purpose  : Returns owner SID in the specified security descriptor.       */
618 /*            If specified security descriptor does not have an owner field */
619 /*            then returns NULL                                             */
620 /******************************************************************************/
621 /***/
622 PSID GetSecurityDescriptorOwnerEx ( PSECURITY_DESCRIPTOR pSD ) {
623
624  BOOL bDummy;
625  PSID retVal;
626
627  if (  !GetSecurityDescriptorOwner ( pSD, &retVal, &bDummy )  )
628   
629   retVal = NULL;
630
631  return retVal;
632
633 }  /* end GetSecurityDescriptorOwnerEx */
634 /***/
635 /******************************************************************************/
636 /* Function : GetSecurityDescriptorGroupEx                                  */
637 /* Purpose  : Returns primary group SID in the specified security           */
638 /*            descriptor. If specified security descriptor does not have a  */
639 /*            primary group field then returns NULL                         */
640 /******************************************************************************/
641 /***/
642 PSID GetSecurityDescriptorGroupEx ( PSECURITY_DESCRIPTOR pSD ) {
643
644  BOOL bDummy;
645  PSID retVal;
646
647  if (  !GetSecurityDescriptorGroup ( pSD, &retVal, &bDummy )  )
648   
649   retVal = NULL;
650
651  return retVal;
652
653 }  /* end GetSecurityDescriptorGroupEx */
654 /***/
655 /******************************************************************************/
656 /* Function : GetSecurityDescriptorDaclEx                                   */
657 /* Purpose  : Returns a pointer to the discretionary access-control list in */
658 /*            the specified security descriptor. If specified security      */
659 /*            descriptor does not have a discretionary access-control list  */
660 /*            then returns NULL                                             */
661 /******************************************************************************/
662 /***/
663 PACL GetSecurityDescriptorDaclEx ( PSECURITY_DESCRIPTOR pSD ) {
664
665  PACL retVal;
666  BOOL bDummy;
667  BOOL fPresent;
668
669  if (  !GetSecurityDescriptorDacl ( pSD, &fPresent, &retVal, &bDummy ) ||
670        !fPresent
671  )
672
673   retVal = NULL;
674
675  return retVal;
676  
677 }  /* end GetSecurityDescriptorDaclEx */
678 /***/
679 /******************************************************************************/
680 /* Function : CreateAcl                                                     */
681 /* Purpose  : Allocates and initializes access-control list                 */
682 /* Returns  : Pointer to the allocated and initialized ACL on success,      */
683 /*            NULL otherwise                                                */
684 /* Warning  : Allocated ACL must be deallocated by 'FreeAcl' function       */
685 /******************************************************************************/
686 /***/
687 PACL CreateAcl ( DWORD dwAclSize ) {
688
689  PACL retVal;
690
691  retVal = ( PACL )HeapAlloc ( hHeap, 0, dwAclSize );
692
693  if ( retVal != NULL )
694
695   InitializeAcl ( retVal, dwAclSize, ACL_REVISION );
696
697  return retVal;
698
699 }  /* end CreateAcl */
700 /***/
701 /******************************************************************************/
702 /* Function : FreeAcl                                                       */
703 /* Purpose  : Deallocates access-control list which was allocated by the    */
704 /*            'CreateAcl' function                                          */
705 /******************************************************************************/
706 /***/
707 void FreeAcl ( PACL pACL ) {
708
709  HeapFree (  hHeap, 0, ( PVOID )pACL  );
710
711 }  /* end FreeAcl */
712 /***/
713 /******************************************************************************/
714 /* Function : CopySidEx                                                     */
715 /* Purpose  : Makes a copy of the SID                                       */
716 /* Returns  : Pointer to the copy of the specified SID on success,          */
717 /*            NULL otherwise                                                */
718 /* Warning  : Allocated SID must be deallocated by 'FreeSidEx' function     */
719 /******************************************************************************/
720 /***/
721 PSID CopySidEx ( PSID pSIDsrc ) {
722
723  DWORD dwLen;
724  PSID  retVal;
725
726  dwLen  = GetLengthSid ( pSIDsrc );
727  retVal = ( PSID )HeapAlloc ( hHeap, 0, dwLen );
728
729  if ( retVal != NULL )
730
731   CopySid ( dwLen, retVal, pSIDsrc );
732
733  return retVal;
734
735 }  /* end CopySidEx */
736 /***/
737 /******************************************************************************/
738 /* Function : FreeSidEx                                                     */
739 /* Purpose  : Deallocates SID which was allocated by the 'CopySidEx'        */
740 /*            function                                                      */
741 /******************************************************************************/
742 /***/
743 void FreeSidEx ( PSID pSID ) {
744
745  HeapFree ( hHeap, 0, pSID );
746
747 }  /* end FreeSidEx */
748 /***/
749 /******************************************************************************/
750 /* Function : AllocGroupSid                                                 */
751 /* Purpose  : Allocates a structure which holds SIDs of groups which are    */
752 /*            not predefined. These SIDs is taking from the DACL of the     */
753 /*            specified security descriptor                                 */
754 /* Returns  : Pointer the allocated structure on success,                   */
755 /*            NULL otherwise                                                */
756 /* Warning  : Allocated structure must be deallocated by 'FreeGroupSid'     */
757 /*            function                                                      */
758 /******************************************************************************/
759 /***/
760 PGROUP_SID AllocGroupSid ( PSECURITY_DESCRIPTOR pSD ) {
761
762  int        i;
763  PGROUP_SID retVal  = NULL;
764  PSID*      pSID    = NULL;
765  DWORD      dwLen;
766  DWORD      dwCount = 0;
767  LPVOID     pACE;
768  PACL       pACL;
769  PSID       pSIDowner;
770  PSID       pSIDadmin;
771  PSID       pSIDworld;
772  BOOL       fPresent;
773  BOOL       fDefaulted;
774
775  if (  GetSecurityDescriptorDacl ( pSD, &fPresent, &pACL, &fDefaulted ) &&
776        fPresent                                                         &&
777        GetSecurityDescriptorOwner ( pSD, &pSIDowner, &fDefaulted )      &&
778        pSIDowner != NULL                                                &&
779        (   retVal = ( PGROUP_SID )HeapAlloc (  hHeap, 0, sizeof ( GROUP_SID )  )   ) !=
780         NULL
781  ) {
782
783   pSIDadmin = AdminSid ();
784   pSIDworld = WorldSid ();
785  
786   for ( i = 0; i < ( int )pACL -> AceCount; ++i )
787     if ( GetAce ( pACL, i, &pACE )                  &&
788          !EqualSid (  pSIDadmin, GET_SID( pACE )  ) &&
789          !EqualSid (  pSIDworld, GET_SID( pACE )  ) &&
790          !EqualSid (  pSIDowner, GET_SID( pACE )  ) )
791       ++dwCount;
792
793   pSID    = ( PSID* )HeapAlloc (  hHeap, 0, dwCount * sizeof ( PSID )  );
794   dwCount = 0;
795
796   if ( pSID != NULL ) {
797   
798    for ( i = 0; i < ( int )pACL -> AceCount; ++i )
799   
800     if (  GetAce ( pACL, i, &pACE )                  &&
801           !EqualSid (  pSIDadmin, GET_SID( pACE )  ) &&
802           !EqualSid (  pSIDworld, GET_SID( pACE )  ) &&
803           !EqualSid (  pSIDowner, GET_SID( pACE )  )
804     ) {
805    
806      pSID[ dwCount ] = ( PSID )HeapAlloc (
807                                 hHeap, 0, dwLen = GetLengthSid (  GET_SID( pACE )  )
808                                );
809
810      if ( pSID[ dwCount ] != NULL )
811
812       CopySid (  dwLen, pSID[ dwCount++ ], GET_SID( pACE )  );
813    
814     }  /* end if */
815
816   }  /* end if */
817     
818   retVal -> nCount = dwCount;
819   retVal -> pSID   = pSID;
820
821  }  /* end if */
822
823  return retVal;
824
825 }  /* end AllocGroupSid */
826 /***/
827 /******************************************************************************/
828 /* Function : FreeGroupSid                                                  */
829 /* Purpose  : Deallocates a structure which was allocated by the            */
830 /*            'AllocGroupSid' function                                      */
831 /******************************************************************************/
832 /***/
833 void FreeGroupSid ( PGROUP_SID pGSID ) {
834
835  int i;
836
837  for ( i = 0; i < ( int )pGSID -> nCount; ++i )
838
839   HeapFree ( hHeap, 0, pGSID -> pSID[ i ] );
840
841  HeapFree ( hHeap, 0, pGSID -> pSID );
842  HeapFree ( hHeap, 0, pGSID         );
843
844 }  /* end FreeGroupSid */
845 /***/
846 /******************************************************************************/
847 /* Function : AllocAccessAllowedAce                                         */
848 /* Purpose  : Allocates and initializes access-control entry                */
849 /* Returns  : Pointer to the ACE on success, NULL othrwise                  */
850 /* Warning  : Allocated ACE must be deallocated by the 'FreeAce' function   */
851 /******************************************************************************/
852 /***/
853 PVOID AllocAccessAllowedAce ( DWORD dwMask, BYTE flags, PSID pSID ) {
854
855  PFILE_ACE retVal;
856  WORD      wSize;
857
858  wSize = (WORD)( sizeof ( ACE_HEADER ) + sizeof ( DWORD ) + GetLengthSid ( pSID ) );
859
860  retVal = ( PFILE_ACE )HeapAlloc ( hHeap, 0, wSize );
861
862  if ( retVal != NULL ) {
863  
864   retVal -> header.AceType  = ACCESS_ALLOWED_ACE_TYPE;
865   retVal -> header.AceFlags = flags;
866   retVal -> header.AceSize  = wSize;
867
868   retVal -> dwMask = dwMask;
869
870   CopySid (  GetLengthSid ( pSID ), &retVal -> pSID, pSID  );
871  
872  }  /* end if */
873
874  return retVal;
875
876 }  /* end AllocAccessAllowedAce */
877 /***/
878 /******************************************************************************/
879 /* Function : FreeAce                                                       */
880 /* Purpose  : Deallocates an ACE which was allocated by the                 */
881 /*            'AllocAccessAllowedAce ' function                             */
882 /******************************************************************************/
883 /***/
884 void FreeAce ( PVOID pACE ) {
885
886  HeapFree ( hHeap, 0, pACE );
887
888 }  /* end FreeAce */
889
890 #define WILD_CARD     L"/*.*"
891 #define WILD_CARD_LEN (  sizeof ( WILD_CARD )  )
892
893 /***/
894 /******************************************************************************/
895 /* Function : MoveDirectory                                                 */
896 /* Purpose  : Moves specified directory tree to the new location            */
897 /* Returns  : TRUE on success, FALSE otherwise                              */
898 /******************************************************************************/
899 /***/
900 BOOL MoveDirectory ( LPCWSTR oldDir, LPCWSTR newDir ) {
901
902  PWIN32_FIND_DATAW    pFD;
903  LPWSTR               pName;
904  LPWSTR               pFullNameSrc;
905  LPWSTR               pFullNameDst;
906  LPWSTR               driveSrc, driveDst;
907  LPWSTR               pathSrc,  pathDst;
908  HANDLE               hFindFile;
909  BOOL                 fFind;
910  BOOL                 retVal = FALSE;
911  DIR_RESPONSE         response;
912  DWORD                level;
913
914  if (   (  level = ( DWORD )TlsGetValue ( dwLevel )  ) == NULL   ) {
915
916   ++level;
917   TlsSetValue (  dwLevel, ( LPVOID )level  );
918
919   fFind = FALSE;
920   driveSrc = driveDst = pathSrc = pathDst = NULL;
921  
922   if (   (  driveSrc = ( LPWSTR )HeapAlloc ( hHeap, 0, _MAX_DRIVE * sizeof(WCHAR) )  ) != NULL &&
923          (  driveDst = ( LPWSTR )HeapAlloc ( hHeap, 0, _MAX_DRIVE * sizeof(WCHAR) )  ) != NULL &&
924          (  pathSrc  = ( LPWSTR )HeapAlloc ( hHeap, 0, _MAX_DIR * sizeof(WCHAR)   )  ) != NULL &&
925          (  pathDst  = ( LPWSTR )HeapAlloc ( hHeap, 0, _MAX_DIR * sizeof(WCHAR)   )  ) != NULL
926   ) {
927   
928    _wsplitpath ( oldDir, driveSrc, pathSrc, NULL, NULL );
929    _wsplitpath ( newDir, driveDst, pathDst, NULL, NULL );
930
931    if (  wcscmp ( driveSrc, driveDst ) == 0 &&
932          wcscmp ( pathSrc,  pathDst  ) == 0
933    ) {
934 retry:   
935     retVal = MoveFileExW (
936               oldDir, newDir, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED
937              );
938     fFind  = TRUE;
939
940     if ( !retVal ) {
941     
942      if ( _response_dir_proc != NULL ) {
943      
944       response = ( *_response_dir_proc ) ( oldDir );
945
946       if ( response == DIR_RETRY )
947
948        goto retry;
949
950       else if ( response == DIR_IGNORE )
951
952        retVal = TRUE;
953
954      }  /* end if */
955     
956     } else if ( _move_dir_proc != NULL )
957
958      ( *_move_dir_proc ) ( oldDir, newDir );
959     
960    }  /* end if */
961   
962   }  /* end if */
963
964   if ( pathDst  != NULL ) HeapFree ( hHeap, 0, pathDst  );
965   if ( pathSrc  != NULL ) HeapFree ( hHeap, 0, pathSrc  );
966   if ( driveDst != NULL ) HeapFree ( hHeap, 0, driveDst );
967   if ( driveSrc != NULL ) HeapFree ( hHeap, 0, driveSrc );
968
969   if ( fFind ) {
970     
971    --level;
972    TlsSetValue (  dwLevel, ( LPVOID )level  );
973    return retVal;
974
975   }  // end if
976  
977  } else {
978  
979   ++level;
980   TlsSetValue (  dwLevel, ( LPVOID )level  );
981  
982  }  // end else
983
984  pFD          = NULL;
985  pName        = NULL;
986  pFullNameSrc = pFullNameDst = NULL;
987  hFindFile    = INVALID_HANDLE_VALUE;
988  retVal       = FALSE;
989
990  retVal = CreateDirectoryW ( newDir, NULL );
991
992  if (   retVal || (  !retVal && GetLastError () == ERROR_ALREADY_EXISTS  )   ) {
993
994   if (   (  pFD = ( PWIN32_FIND_DATAW )HeapAlloc (
995                                        hHeap, 0, sizeof ( WIN32_FIND_DATAW )
996                                       )
997          ) != NULL &&
998          (  pName = ( LPWSTR )HeapAlloc (
999                                hHeap, 0, lstrlenW ( oldDir ) + WILD_CARD_LEN +
1000                                sizeof (  L'\x00'  )
1001                               )
1002          ) != NULL
1003   ) {
1004
1005    lstrcpyW ( pName, oldDir    );
1006    lstrcatW ( pName, WILD_CARD );
1007
1008    retVal = TRUE;
1009    fFind  = (  hFindFile = FindFirstFileW ( pName, pFD )  ) != INVALID_HANDLE_VALUE;
1010
1011    while ( fFind ) {
1012   
1013     if (  pFD -> cFileName[ 0 ] != L'.' ||
1014           pFD -> cFileName[ 0 ] != L'.' &&
1015           pFD -> cFileName[ 1 ] != L'.'
1016     ) {
1017   
1018      if (   ( pFullNameSrc = ( LPWSTR )HeapAlloc (
1019                                         hHeap, 0,
1020                                         lstrlenW ( oldDir ) + lstrlenW ( pFD -> cFileName ) +
1021                                         sizeof (  L'/'  ) + sizeof ( L'\x00'  )
1022                                        )
1023             ) == NULL ||
1024             ( pFullNameDst = ( LPWSTR )HeapAlloc (
1025                                         hHeap, 0,
1026                                         lstrlenW ( newDir ) + lstrlenW ( pFD -> cFileName ) +
1027                                         sizeof (  L'/'  ) + sizeof (  L'\x00'  )
1028                                        )
1029             ) == NULL
1030      ) break;
1031   
1032      lstrcpyW ( pFullNameSrc, oldDir );
1033      lstrcatW ( pFullNameSrc, L"/"  );
1034      lstrcatW ( pFullNameSrc, pFD -> cFileName );
1035
1036      lstrcpyW ( pFullNameDst, newDir );
1037      lstrcatW ( pFullNameDst, L"/"  );
1038      lstrcatW ( pFullNameDst, pFD -> cFileName );
1039
1040      if ( pFD -> dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
1041
1042        retVal = MoveDirectory ( pFullNameSrc, pFullNameDst );
1043        if (!retVal) break;
1044    
1045      } else {
1046 retry_1:   
1047       retVal = MoveFileExW (pFullNameSrc, pFullNameDst,
1048                             MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
1049       if (! retVal) {
1050       
1051        if ( _response_dir_proc != NULL ) {
1052       
1053         response = ( *_response_dir_proc ) ( pFullNameSrc );
1054
1055         if ( response == DIR_ABORT )
1056
1057          break;
1058
1059         else if ( response == DIR_RETRY )
1060
1061          goto retry_1;
1062
1063         else if ( response == DIR_IGNORE )
1064
1065          retVal = TRUE;
1066
1067         else
1068
1069          break;
1070
1071        }  /* end if */
1072       
1073       } else if ( _move_dir_proc != NULL )
1074
1075        ( *_move_dir_proc ) ( pFullNameSrc, pFullNameDst );
1076
1077      }  /* end else */
1078
1079      HeapFree ( hHeap, 0, pFullNameDst );
1080      HeapFree ( hHeap, 0, pFullNameSrc );
1081      pFullNameSrc = pFullNameDst = NULL;
1082
1083     }  /* end if */
1084
1085     fFind = FindNextFileW ( hFindFile, pFD );
1086
1087    }  /* end while */
1088
1089   }  /* end if */
1090
1091  }  /* end if ( error creating directory ) */
1092
1093  if ( hFindFile != INVALID_HANDLE_VALUE ) FindClose ( hFindFile );
1094
1095  if ( pFullNameSrc != NULL ) HeapFree ( hHeap, 0, pFullNameSrc );
1096  if ( pFullNameDst != NULL ) HeapFree ( hHeap, 0, pFullNameDst );
1097  if ( pName        != NULL ) HeapFree ( hHeap, 0, pName        );
1098  if ( pFD          != NULL ) HeapFree ( hHeap, 0, pFD          );
1099
1100  if ( retVal ) {
1101 retry_2:  
1102   retVal = RemoveDirectoryW ( oldDir );
1103
1104   if ( !retVal ) {
1105   
1106    if ( _response_dir_proc != NULL ) {
1107       
1108     response = ( *_response_dir_proc ) ( oldDir );
1109
1110     if ( response == DIR_RETRY )
1111
1112      goto retry_2;
1113
1114     else if ( response == DIR_IGNORE )
1115
1116      retVal = TRUE;
1117
1118    }  /* end if */
1119
1120   }  /* end if */
1121   
1122  }  /* end if */
1123
1124  --level;
1125  TlsSetValue (  dwLevel, ( LPVOID )level  );
1126
1127  return retVal;
1128
1129 }  /* end MoveDirectory */
1130 /***/
1131 /******************************************************************************/
1132 /* Function : CopyDirectory                                                 */
1133 /* Purpose  : Copies specified directory tree to the new location           */
1134 /* Returns  : TRUE on success, FALSE otherwise                              */
1135 /******************************************************************************/
1136 /***/
1137 BOOL CopyDirectory ( LPCWSTR dirSrc, LPCWSTR dirDst ) {
1138
1139  PWIN32_FIND_DATAW    pFD = NULL;
1140  LPWSTR               pName = NULL;
1141  LPWSTR               pFullNameSrc = NULL;
1142  LPWSTR               pFullNameDst = NULL;
1143  HANDLE               hFindFile = INVALID_HANDLE_VALUE;
1144  BOOL                 fFind;
1145  BOOL                 retVal = FALSE;
1146  DIR_RESPONSE         response;
1147
1148  retVal = CreateDirectoryW ( dirDst, NULL );
1149
1150  if (   retVal || (  !retVal && GetLastError () == ERROR_ALREADY_EXISTS  )   ) {
1151
1152   if (   (  pFD = ( PWIN32_FIND_DATAW )HeapAlloc (
1153                                        hHeap, 0, sizeof ( WIN32_FIND_DATAW )
1154                                       )
1155          ) != NULL &&
1156          (  pName = ( LPWSTR )HeapAlloc (
1157                                hHeap, 0, lstrlenW ( dirSrc ) + WILD_CARD_LEN +
1158                                sizeof (  L'\x00'  )
1159                               )
1160          ) != NULL
1161   ) {
1162
1163    lstrcpyW ( pName, dirSrc    );
1164    lstrcatW ( pName, WILD_CARD );
1165
1166    retVal = TRUE;
1167    fFind  = (  hFindFile = FindFirstFileW ( pName, pFD )  ) != INVALID_HANDLE_VALUE;
1168
1169    while ( fFind ) {
1170   
1171     if (  pFD -> cFileName[ 0 ] != L'.' ||
1172           pFD -> cFileName[ 0 ] != L'.' &&
1173           pFD -> cFileName[ 1 ] != L'.'
1174     ) {
1175   
1176      if (   ( pFullNameSrc = ( LPWSTR )HeapAlloc (
1177                                         hHeap, 0,
1178                                         lstrlenW ( dirSrc ) + lstrlenW ( pFD -> cFileName ) +
1179                                         sizeof (  L'/'  ) + sizeof (  L'\x00'  )
1180                                        )
1181             ) == NULL ||
1182             ( pFullNameDst = ( LPWSTR )HeapAlloc (
1183                                         hHeap, 0,
1184                                         lstrlenW ( dirDst ) + lstrlenW ( pFD -> cFileName ) +
1185                                         sizeof (  L'/'  ) + sizeof (  L'\x00'  )
1186                                        )
1187             ) == NULL
1188      ) break;
1189   
1190      lstrcpyW ( pFullNameSrc, dirSrc );
1191      lstrcatW ( pFullNameSrc, L"/"  );
1192      lstrcatW ( pFullNameSrc, pFD -> cFileName );
1193
1194      lstrcpyW ( pFullNameDst, dirDst );
1195      lstrcatW ( pFullNameDst, L"/"  );
1196      lstrcatW ( pFullNameDst, pFD -> cFileName );
1197
1198      if ( pFD -> dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
1199
1200        retVal = CopyDirectory ( pFullNameSrc, pFullNameDst );
1201        if ( ! retVal ) break;
1202    
1203      } else {
1204 retry:   
1205       retVal = CopyFileW ( pFullNameSrc, pFullNameDst, FALSE );
1206       if ( ! retVal ) {
1207       
1208        if ( _response_dir_proc != NULL ) {
1209       
1210         response = ( *_response_dir_proc ) ( pFullNameSrc );
1211
1212         if ( response == DIR_ABORT )
1213
1214          break;
1215
1216         else if ( response == DIR_RETRY )
1217
1218          goto retry;
1219
1220         else if ( response == DIR_IGNORE )
1221
1222          retVal = TRUE;
1223
1224         else
1225
1226          break;
1227
1228        }  /* end if */
1229       
1230       } else if ( _copy_dir_proc != NULL )
1231
1232        ( *_copy_dir_proc ) ( pFullNameSrc, pFullNameDst );
1233
1234      }  /* end else */
1235
1236      HeapFree ( hHeap, 0, pFullNameDst );
1237      HeapFree ( hHeap, 0, pFullNameSrc );
1238      pFullNameSrc = pFullNameDst = NULL;
1239
1240     }  /* end if */
1241
1242     fFind = FindNextFileW ( hFindFile, pFD );
1243
1244    }  /* end while */
1245
1246   }  /* end if */
1247
1248  }  /* end if ( error creating directory ) */
1249
1250  if ( hFindFile != INVALID_HANDLE_VALUE ) FindClose ( hFindFile );
1251
1252  if ( pFullNameSrc != NULL ) HeapFree ( hHeap, 0, pFullNameSrc );
1253  if ( pFullNameDst != NULL ) HeapFree ( hHeap, 0, pFullNameDst );
1254  if ( pName        != NULL ) HeapFree ( hHeap, 0, pName        );
1255  if ( pFD          != NULL ) HeapFree ( hHeap, 0, pFD          );
1256
1257  return retVal;
1258
1259 }  /* end CopyDirectory */
1260 /***/
1261 /******************************************************************************/
1262 /* Function : SetMoveDirectoryProc                                          */
1263 /* Purpose  : Sets callback procedure which is calling by the               */ 
1264 /*            'MoveDirectory' after moving of each item in the              */
1265 /*            directory. To unregister this callback function supply NULL   */
1266 /*            pointer                                                       */
1267 /******************************************************************************/
1268 /***/
1269 void SetMoveDirectoryProc ( MOVE_DIR_PROC proc ) {
1270
1271  _move_dir_proc = proc;
1272
1273 }  /* end SetMoveDirectoryProc */
1274 /***/
1275 /******************************************************************************/
1276 /* Function : SetCopyDirectoryProc                                          */
1277 /* Purpose  : Sets callback procedure which is calling by the               */ 
1278 /*            'CopyDirectory' after copying of each item in the             */
1279 /*            directory. To unregister this callback function supply NULL   */
1280 /*            pointer                                                       */
1281 /******************************************************************************/
1282 /***/
1283 void SetCopyDirectoryProc ( COPY_DIR_PROC proc ) {
1284
1285  _copy_dir_proc = proc;
1286
1287 }  /* end SetCopyDirectoryProc */
1288 /***/
1289 /******************************************************************************/
1290 /* Function : SetResponseDirectoryProc                                      */
1291 /* Purpose  : Sets callback procedure which is calling by the               */ 
1292 /*            directoy processing function if an error was occur.           */
1293 /*            The return value of that callback procedure determines        */
1294 /*            behaviour of directoy processing functions in case of error.  */
1295 /*            To unregister this callback function supply NULL pointer      */
1296 /******************************************************************************/
1297 /***/
1298 void SetResponseDirectoryProc ( RESPONSE_DIR_PROC proc ) {
1299
1300  _response_dir_proc = proc;
1301
1302 }  /* end SetResponseDirectoryProc */
1303 /***/
1304 /******************************************************************************/
1305 /******************************************************************************/
1306 /******************************************************************************/
1307 #endif