1 // Created by: PLOTNIKOV Eugeny
2 // Copyright (c) 1996-1999 Matra Datavision
3 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
18 /******************************************************************************/
19 /* File: OSD_WNT.cxx */
20 /* Purpose: Security management routines ( more convinient than WIN32 */
21 /* ones ) and other convinient functions. */
22 /******************************************************************************/
24 #include <OSD_WNT.hxx>
30 #include <Standard_Macro.hxx>
34 static void Init ( void );
36 class Init_OSD_WNT { // provides initialization
40 Init_OSD_WNT () { Init (); }
42 }; // end Init_OSD_WNT
44 static Init_OSD_WNT initOsdWnt;
47 static BOOL fInit = FALSE;
48 static PSID* predefinedSIDs;
51 static MOVE_DIR_PROC _move_dir_proc;
52 static COPY_DIR_PROC _copy_dir_proc;
53 static RESPONSE_DIR_PROC _response_dir_proc;
55 #define PREDEFINED_SIDs_COUNT 9
56 #define UNIVERSAL_PREDEFINED_SIDs_COUNT 5
58 #define SID_INTERACTIVE 0
63 #define SID_CREATOR_OWNER 5
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 /******************************************************************************/
77 PSECURITY_DESCRIPTOR AllocSD ( void ) {
79 PSECURITY_DESCRIPTOR retVal =
80 ( PSECURITY_DESCRIPTOR )HeapAlloc (
81 hHeap, 0, sizeof ( SECURITY_DESCRIPTOR )
84 if ( retVal != NULL &&
85 !InitializeSecurityDescriptor ( retVal, SECURITY_DESCRIPTOR_REVISION )
88 HeapFree ( hHeap, 0, ( PVOID )retVal );
97 /******************************************************************************/
98 /* Function : FreeSD */
99 /* Purpose : Deallocates security identifier which was allocated by the */
100 /* 'AllocSD' function */
101 /******************************************************************************/
103 void FreeSD ( PSECURITY_DESCRIPTOR pSD ) {
109 if ( GetSecurityDescriptorDacl ( pSD, &fPresent, &pACL, &fDaclDefaulted ) &&
113 HeapFree ( hHeap, 0, ( PVOID )pACL );
115 HeapFree ( hHeap, 0, ( PVOID )pSD );
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 /******************************************************************************/
128 #if defined(__CYGWIN32__) || defined(__MINGW32__)
131 #define __leave return buffer
134 LPVOID GetTokenInformationEx ( HANDLE hToken, TOKEN_INFORMATION_CLASS tic ) {
138 DWORD dwSizeNeeded = 0;
139 LPVOID buffer = NULL;
146 dwSize = dwSizeNeeded;
147 errVal = ERROR_SUCCESS;
149 if ( !GetTokenInformation ( hToken, tic, buffer, dwSize, &dwSizeNeeded ) ) {
151 if ( ( errVal = GetLastError () ) != ERROR_INSUFFICIENT_BUFFER )
155 if ( ( buffer = HeapAlloc ( hHeap, 0, dwSizeNeeded ) ) == NULL )
161 } while ( errVal != ERROR_SUCCESS );
169 if ( !fOK && buffer != NULL ) {
171 HeapFree ( hHeap, 0, buffer );
176 } /* end __finally */
179 leave: ; // added for VisualAge
184 } /* end GetTokenInformationEx */
186 #if defined(__CYGWIN32__) || defined(__MINGW32__)
193 /******************************************************************************/
194 /* Function : FreeTokenInformation */
195 /* Purpose : Deallocates access token which was allocated by the */
196 /* 'GetTokenInformationEx' function */
197 /******************************************************************************/
199 void FreeTokenInformation ( LPVOID lpvTkInfo ) {
201 HeapFree ( hHeap, 0, lpvTkInfo );
203 } /* end FreeTokenInformation */
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 /******************************************************************************/
214 static void Init ( void ) {
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;
224 predefinedSIDs = ( PSID* )HeapAlloc (
225 hHeap = GetProcessHeap (),
226 HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
227 PREDEFINED_SIDs_COUNT * sizeof ( PSID* )
230 AllocateAndInitializeSid (
231 &sidIDANT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
232 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_ADMIN ]
235 AllocateAndInitializeSid (
236 &sidIDAworld, 1, SECURITY_WORLD_RID,
237 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_WORLD ]
240 AllocateAndInitializeSid (
241 &sidIDANT, 1, SECURITY_INTERACTIVE_RID,
242 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_INTERACTIVE ]
245 AllocateAndInitializeSid (
246 &sidIDANT, 1, SECURITY_NETWORK_RID,
247 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_NETWORK ]
250 AllocateAndInitializeSid (
251 &sidIDAlocal, 1, SECURITY_LOCAL_RID,
252 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_LOCAL ]
255 AllocateAndInitializeSid (
256 &sidIDANT, 1, SECURITY_DIALUP_RID,
257 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_DIALUP ]
260 AllocateAndInitializeSid (
261 &sidIDANT, 1, SECURITY_BATCH_RID,
262 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_BATCH ]
265 AllocateAndInitializeSid (
266 &sidIDAcreator, 1, SECURITY_CREATOR_OWNER_RID,
267 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_CREATOR_OWNER ]
270 AllocateAndInitializeSid (
271 &sidIDAnull, 1, SECURITY_NULL_RID,
272 0, 0, 0, 0, 0, 0, 0, &predefinedSIDs[ SID_NULL ]
281 /******************************************************************************/
282 /* Function : PredefinedSid */
283 /* Purpose : Checks whether specified SID predefined or not */
284 /* Returns : TRUE if specified SID is predefined, FALSE otherwise */
285 /******************************************************************************/
287 BOOL PredefinedSid ( PSID pSID ) {
291 for ( i = 0; i < PREDEFINED_SIDs_COUNT; ++i )
293 if ( EqualSid ( pSID, predefinedSIDs[ i ] ) )
299 } /* end PredefinedSid */
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 /******************************************************************************/
307 BOOL NtPredefinedSid ( PSID pSID ) {
310 PSID_IDENTIFIER_AUTHORITY pTestIDA;
311 SID_IDENTIFIER_AUTHORITY ntIDA = SECURITY_NT_AUTHORITY;
314 for ( i = 0; i < UNIVERSAL_PREDEFINED_SIDs_COUNT; ++i )
316 if ( EqualSid ( pSID, predefinedSIDs[ i ] ) )
320 pTestIDA = GetSidIdentifierAuthority ( pSID );
322 if ( memcmp ( pTestIDA, &ntIDA, sizeof ( SID_IDENTIFIER_AUTHORITY ) ) == 0 ) {
324 pdwTestSA = GetSidSubAuthority ( pSID, 0 );
326 if ( *pdwTestSA == SECURITY_LOGON_IDS_RID )
334 } /* end NtPredefinedSid */
336 /******************************************************************************/
337 /* Function : AdminSid */
338 /* Purpose : Returns SID of the administrative user account */
339 /******************************************************************************/
341 PSID AdminSid ( void ) {
343 return predefinedSIDs[ SID_ADMIN ];
347 /******************************************************************************/
348 /* Function : WorldSid */
349 /* Purpose : Returns SID of group that includes all users */
350 /******************************************************************************/
352 PSID WorldSid ( void ) {
354 return predefinedSIDs[ SID_WORLD ];
358 /******************************************************************************/
359 /* Function : InteractiveSid */
360 /* Purpose : Returns SID of group that includes all users logged on for */
361 /* interactive operation */
362 /******************************************************************************/
364 PSID InteractiveSid ( void ) {
366 return predefinedSIDs[ SID_INTERACTIVE ];
368 } /* end InteractiveSID */
370 /******************************************************************************/
371 /* Function : NetworkSid */
372 /* Purpose : Returns SID of group that includes all users logged on across */
374 /******************************************************************************/
376 PSID NetworkSid ( void ) {
378 return predefinedSIDs[ SID_NETWORK ];
380 } /* end NetworkSid */
382 /******************************************************************************/
383 /* Function : LocalSid */
384 /* Purpose : Returns SID of group that includes all users logged on locally*/
385 /******************************************************************************/
387 PSID LocalSid ( void ) {
389 return predefinedSIDs[ SID_LOCAL ];
393 /******************************************************************************/
394 /* Function : DialupSid */
395 /* Purpose : Returns SID of group that includes all users logged on to */
396 /* terminals using a dialup modem */
397 /******************************************************************************/
399 PSID DialupSid ( void ) {
401 return predefinedSIDs[ SID_DIALUP ];
403 } /* end DialupSid */
405 /******************************************************************************/
406 /* Function : BatchSid */
407 /* Purpose : Returns SID of group that includes all users logged on using */
408 /* a batch queue facility */
409 /******************************************************************************/
411 PSID BatchSid ( void ) {
413 return predefinedSIDs[ SID_BATCH ];
417 /******************************************************************************/
418 /* Function : CreatorOwnerSid */
419 /* Purpose : Returns SID of 'CREATOR OWNER' special group */
420 /******************************************************************************/
422 PSID CreatorOwnerSid ( void ) {
424 return predefinedSIDs[ SID_CREATOR_OWNER ];
426 } /* end CreatorOwnerSid */
428 /******************************************************************************/
429 /* Function : NullSid */
430 /* Purpose : Returns null SID */
431 /******************************************************************************/
433 PSID NullSid ( void ) {
435 return predefinedSIDs[ SID_NULL ];
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 */
445 /* Warning : Allocated security descriptor must be deallocated by */
446 /* 'FreeFileSecurity' function */
447 /******************************************************************************/
451 #if defined(__CYGWIN32__) || defined(__MINGW32__)
454 #define __leave return retVal
457 PSECURITY_DESCRIPTOR GetFileSecurityEx ( LPCWSTR fileName, SECURITY_INFORMATION si ) {
461 DWORD dwSizeNeeded = 0;
462 PSECURITY_DESCRIPTOR retVal = NULL;
469 dwSize = dwSizeNeeded;
470 errVal = ERROR_SUCCESS;
472 if ( !GetFileSecurityW (
474 retVal, dwSize, &dwSizeNeeded
478 if ( ( errVal = GetLastError () ) != ERROR_INSUFFICIENT_BUFFER ) __leave;
480 if ( ( retVal = ( PSECURITY_DESCRIPTOR )HeapAlloc ( hHeap, 0, dwSizeNeeded )
486 } while ( errVal != ERROR_SUCCESS );
494 if ( !fOK && retVal != NULL ) {
496 HeapFree ( hHeap, 0, retVal );
501 } /* end __finally */
504 leave: ; // added for VisualAge
509 } /* end GetFileSecurityEx */
511 #if defined(__CYGWIN32__) || defined(__MINGW32__)
518 /******************************************************************************/
519 /* Function : FreeFileSecurity */
520 /* Purpose : Deallocates security descriptor which was allocated by the */
521 /* 'GetFileSecurityEx' function */
522 /******************************************************************************/
524 void FreeFileSecurity ( PSECURITY_DESCRIPTOR pSD ) {
526 HeapFree ( hHeap, 0, ( LPVOID )pSD );
528 } /* end FreeFileSecurity */
531 /******************************************************************************/
532 /* Function : CreateAcl */
533 /* Purpose : Allocates and initializes access-control list */
534 /* Returns : Pointer to the allocated and initialized ACL on success, */
536 /* Warning : Allocated ACL must be deallocated by 'FreeAcl' function */
537 /******************************************************************************/
539 PACL CreateAcl ( DWORD dwAclSize ) {
543 retVal = ( PACL )HeapAlloc ( hHeap, 0, dwAclSize );
545 if ( retVal != NULL )
547 InitializeAcl ( retVal, dwAclSize, ACL_REVISION );
551 } /* end CreateAcl */
553 /******************************************************************************/
554 /* Function : FreeAcl */
555 /* Purpose : Deallocates access-control list which was allocated by the */
556 /* 'CreateAcl' function */
557 /******************************************************************************/
559 void FreeAcl ( PACL pACL ) {
561 HeapFree ( hHeap, 0, ( PVOID )pACL );
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 /******************************************************************************/
572 PVOID AllocAccessAllowedAce ( DWORD dwMask, BYTE flags, PSID pSID ) {
577 wSize = (WORD)( sizeof ( ACE_HEADER ) + sizeof ( DWORD ) + GetLengthSid ( pSID ) );
579 retVal = ( PFILE_ACE )HeapAlloc ( hHeap, 0, wSize );
581 if ( retVal != NULL ) {
583 retVal -> header.AceType = ACCESS_ALLOWED_ACE_TYPE;
584 retVal -> header.AceFlags = flags;
585 retVal -> header.AceSize = wSize;
587 retVal -> dwMask = dwMask;
589 CopySid ( GetLengthSid ( pSID ), &retVal -> pSID, pSID );
595 } /* end AllocAccessAllowedAce */
597 /******************************************************************************/
598 /* Function : FreeAce */
599 /* Purpose : Deallocates an ACE which was allocated by the */
600 /* 'AllocAccessAllowedAce ' function */
601 /******************************************************************************/
603 void FreeAce ( PVOID pACE ) {
605 HeapFree ( hHeap, 0, pACE );
609 #define WILD_CARD L"/*.*"
610 #define WILD_CARD_LEN ( sizeof ( WILD_CARD ) )
613 /******************************************************************************/
614 /* Function : MoveDirectory */
615 /* Purpose : Moves specified directory tree to the new location */
616 /* Returns : TRUE on success, FALSE otherwise */
617 /******************************************************************************/
619 static BOOL MoveDirectory (const wchar_t* oldDir, const wchar_t* newDir, DWORD& theRecurseLevel)
621 wchar_t* driveSrc = NULL;
622 wchar_t* driveDst = NULL;
623 wchar_t* pathSrc = NULL;
624 wchar_t* pathDst = NULL;
626 if (theRecurseLevel == 0)
630 if ((driveSrc = (wchar_t* )HeapAlloc (hHeap, 0, _MAX_DRIVE * sizeof(wchar_t))) != NULL
631 && (driveDst = (wchar_t* )HeapAlloc (hHeap, 0, _MAX_DRIVE * sizeof(wchar_t))) != NULL
632 && (pathSrc = (wchar_t* )HeapAlloc (hHeap, 0, _MAX_DIR * sizeof(wchar_t))) != NULL
633 && (pathDst = (wchar_t* )HeapAlloc (hHeap, 0, _MAX_DIR * sizeof(wchar_t))) != NULL)
635 _wsplitpath (oldDir, driveSrc, pathSrc, NULL, NULL);
636 _wsplitpath (newDir, driveDst, pathDst, NULL, NULL);
637 if (wcscmp (driveSrc, driveDst) == 0
638 && wcscmp (pathSrc, pathDst ) == 0)
641 retVal = MoveFileExW (oldDir, newDir, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
645 if (_response_dir_proc != NULL)
647 const DIR_RESPONSE response = _response_dir_proc (oldDir);
648 if (response == DIR_RETRY)
652 else if (response == DIR_IGNORE)
658 else if (_move_dir_proc != NULL)
660 _move_dir_proc (oldDir, newDir);
667 HeapFree (hHeap, 0, pathDst);
671 HeapFree (hHeap, 0, pathSrc);
673 if (driveDst != NULL)
675 HeapFree (hHeap, 0, driveDst);
677 if (driveSrc != NULL)
679 HeapFree (hHeap, 0, driveSrc);
693 WIN32_FIND_DATAW* pFD = NULL;
694 wchar_t* pName = NULL;
695 wchar_t* pFullNameSrc = NULL;
696 wchar_t* pFullNameDst = NULL;
697 HANDLE hFindFile = INVALID_HANDLE_VALUE;
698 retVal = CreateDirectoryW (newDir, NULL);
699 if (retVal || (!retVal && GetLastError() == ERROR_ALREADY_EXISTS))
701 size_t anOldDirLength;
702 StringCchLengthW (oldDir, sizeof(oldDir) / sizeof(oldDir[0]), &anOldDirLength);
703 if ((pFD = (WIN32_FIND_DATAW* )HeapAlloc (hHeap, 0, sizeof(WIN32_FIND_DATAW))) != NULL
704 && (pName = (wchar_t* )HeapAlloc (hHeap, 0, anOldDirLength + WILD_CARD_LEN + sizeof(L'\x00'))) != NULL)
706 StringCchCopyW (pName, sizeof(pName) / sizeof(pName[0]), oldDir);
707 StringCchCatW (pName, sizeof(pName), WILD_CARD);
709 hFindFile = FindFirstFileExW (pName, FindExInfoStandard, pFD, FindExSearchNameMatch, NULL, 0);
710 for (BOOL fFind = hFindFile != INVALID_HANDLE_VALUE; fFind; fFind = FindNextFileW (hFindFile, pFD))
712 if ((pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'\0')
713 || (pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'.' && pFD->cFileName[2] == L'\0'))
718 size_t anOldDirLength2 = 0, aNewDirLength = 0, aFileNameLength = 0;
719 StringCchLengthW (oldDir, sizeof(oldDir) / sizeof(oldDir[0]), &anOldDirLength2);
720 StringCchLengthW (newDir, sizeof(newDir) / sizeof(newDir[0]), &aNewDirLength);
721 StringCchLengthW (pFD->cFileName, sizeof(pFD->cFileName) / sizeof(pFD->cFileName[0]), &aFileNameLength);
722 if ((pFullNameSrc = (wchar_t* )HeapAlloc (hHeap, 0, anOldDirLength2 + aFileNameLength + sizeof(L'/') + sizeof(L'\x00'))) == NULL
723 || (pFullNameDst = (wchar_t* )HeapAlloc (hHeap, 0, aNewDirLength + aFileNameLength + sizeof(L'/') + sizeof(L'\x00'))) == NULL)
728 StringCchCopyW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), oldDir);
729 StringCchCatW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), L"/");
730 StringCchCatW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), pFD->cFileName);
732 StringCchCopyW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), newDir);
733 StringCchCatW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), L"/");
734 StringCchCatW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), pFD->cFileName);
736 if ((pFD->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
738 retVal = MoveDirectory (pFullNameSrc, pFullNameDst, theRecurseLevel);
747 retVal = MoveFileExW (pFullNameSrc, pFullNameDst, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
750 if (_response_dir_proc != NULL)
752 const DIR_RESPONSE response = _response_dir_proc (pFullNameSrc);
753 if (response == DIR_ABORT)
757 else if (response == DIR_RETRY)
761 else if (response == DIR_IGNORE)
771 else if (_move_dir_proc != NULL)
773 _move_dir_proc (pFullNameSrc, pFullNameDst);
777 HeapFree (hHeap, 0, pFullNameDst);
778 HeapFree (hHeap, 0, pFullNameSrc);
779 pFullNameSrc = pFullNameDst = NULL;
784 if (hFindFile != INVALID_HANDLE_VALUE)
786 FindClose (hFindFile);
789 if (pFullNameSrc != NULL)
791 HeapFree (hHeap, 0, pFullNameSrc);
793 if (pFullNameDst != NULL)
795 HeapFree (hHeap, 0, pFullNameDst);
799 HeapFree (hHeap, 0, pName);
803 HeapFree (hHeap, 0, pFD);
809 retVal = RemoveDirectoryW (oldDir);
812 if (_response_dir_proc != NULL)
814 const DIR_RESPONSE response = _response_dir_proc (oldDir);
815 if (response == DIR_RETRY)
819 else if (response == DIR_IGNORE)
831 BOOL MoveDirectory (const wchar_t* oldDir, const wchar_t* newDir)
833 DWORD aRecurseLevel = 0;
834 return MoveDirectory (oldDir, newDir, aRecurseLevel);
838 /******************************************************************************/
839 /* Function : CopyDirectory */
840 /* Purpose : Copies specified directory tree to the new location */
841 /* Returns : TRUE on success, FALSE otherwise */
842 /******************************************************************************/
844 BOOL CopyDirectory (const wchar_t* dirSrc, const wchar_t* dirDst)
846 WIN32_FIND_DATAW* pFD = NULL;
847 wchar_t* pName = NULL;
848 wchar_t* pFullNameSrc = NULL;
849 wchar_t* pFullNameDst = NULL;
850 HANDLE hFindFile = INVALID_HANDLE_VALUE;
852 BOOL retVal = CreateDirectoryW (dirDst, NULL);
853 if (retVal || (!retVal && GetLastError() == ERROR_ALREADY_EXISTS))
855 size_t aDirSrcLength = 0;
856 StringCchLengthW (dirSrc, sizeof(dirSrc) / sizeof(dirSrc[0]), &aDirSrcLength);
857 if ((pFD = (WIN32_FIND_DATAW* )HeapAlloc (hHeap, 0, sizeof(WIN32_FIND_DATAW))) != NULL
858 && (pName = (wchar_t* )HeapAlloc (hHeap, 0, aDirSrcLength + WILD_CARD_LEN + sizeof(L'\x00'))) != NULL)
860 StringCchCopyW(pName, sizeof(pName) / sizeof(pName[0]), dirSrc);
861 StringCchCatW (pName, sizeof(pName) / sizeof(pName[0]), WILD_CARD);
864 hFindFile = FindFirstFileExW (pName, FindExInfoStandard, pFD, FindExSearchNameMatch, NULL, 0);
865 for (BOOL fFind = hFindFile != INVALID_HANDLE_VALUE; fFind; fFind = FindNextFileW (hFindFile, pFD))
867 if ((pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'\0')
868 || (pFD->cFileName[0] == L'.' && pFD->cFileName[1] == L'.' && pFD->cFileName[2] == L'\0'))
873 size_t aDirSrcLength2 = 0, aDirDstLength = 0, aFileNameLength = 0;
874 StringCchLengthW (dirSrc, sizeof(dirSrc) / sizeof(dirSrc[0]), &aDirSrcLength2);
875 StringCchLengthW (dirDst, sizeof(dirDst) / sizeof(dirDst[0]), &aDirDstLength);
876 StringCchLengthW (pFD->cFileName, sizeof(pFD->cFileName) / sizeof(pFD->cFileName[0]), &aFileNameLength);
877 if ((pFullNameSrc = (wchar_t* )HeapAlloc (hHeap, 0, aDirSrcLength2 + aFileNameLength + sizeof(L'/') + sizeof(L'\x00'))) == NULL
878 || (pFullNameDst = (wchar_t* )HeapAlloc (hHeap, 0, aDirDstLength + aFileNameLength + sizeof(L'/') + sizeof(L'\x00'))) == NULL)
883 StringCchCopyW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), dirSrc);
884 StringCchCatW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), L"/");
885 StringCchCatW (pFullNameSrc, sizeof(pFullNameSrc) / sizeof(pFullNameSrc[0]), pFD->cFileName);
887 StringCchCopyW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), dirDst);
888 StringCchCatW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), L"/");
889 StringCchCatW (pFullNameDst, sizeof(pFullNameDst) / sizeof(pFullNameDst[0]), pFD->cFileName);
890 if ((pFD->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
892 retVal = CopyDirectory (pFullNameSrc, pFullNameDst);
902 retVal = CopyFileW (pFullNameSrc, pFullNameDst, FALSE);
904 retVal = (CopyFile2 (pFullNameSrc, pFullNameDst, FALSE) == S_OK) ? TRUE : FALSE;
908 if (_response_dir_proc != NULL)
910 const DIR_RESPONSE response = _response_dir_proc (pFullNameSrc);
911 if (response == DIR_ABORT)
915 else if (response == DIR_RETRY)
919 else if (response == DIR_IGNORE)
929 else if (_copy_dir_proc != NULL)
931 _copy_dir_proc (pFullNameSrc, pFullNameDst);
935 HeapFree (hHeap, 0, pFullNameDst);
936 HeapFree (hHeap, 0, pFullNameSrc);
937 pFullNameSrc = pFullNameDst = NULL;
942 if (hFindFile != INVALID_HANDLE_VALUE)
944 FindClose (hFindFile);
947 if (pFullNameSrc != NULL)
949 HeapFree (hHeap, 0, pFullNameSrc);
951 if (pFullNameDst != NULL)
953 HeapFree (hHeap, 0, pFullNameDst);
957 HeapFree (hHeap, 0, pName);
961 HeapFree (hHeap, 0, pFD);
965 } /* end CopyDirectory */
967 /******************************************************************************/
968 /* Function : SetMoveDirectoryProc */
969 /* Purpose : Sets callback procedure which is calling by the */
970 /* 'MoveDirectory' after moving of each item in the */
971 /* directory. To unregister this callback function supply NULL */
973 /******************************************************************************/
975 void SetMoveDirectoryProc ( MOVE_DIR_PROC proc ) {
977 _move_dir_proc = proc;
979 } /* end SetMoveDirectoryProc */
981 /******************************************************************************/
982 /* Function : SetCopyDirectoryProc */
983 /* Purpose : Sets callback procedure which is calling by the */
984 /* 'CopyDirectory' after copying of each item in the */
985 /* directory. To unregister this callback function supply NULL */
987 /******************************************************************************/
989 void SetCopyDirectoryProc ( COPY_DIR_PROC proc ) {
991 _copy_dir_proc = proc;
993 } /* end SetCopyDirectoryProc */
995 /******************************************************************************/
996 /* Function : SetResponseDirectoryProc */
997 /* Purpose : Sets callback procedure which is calling by the */
998 /* directoy processing function if an error was occur. */
999 /* The return value of that callback procedure determines */
1000 /* behaviour of directoy processing functions in case of error. */
1001 /* To unregister this callback function supply NULL pointer */
1002 /******************************************************************************/
1004 void SetResponseDirectoryProc ( RESPONSE_DIR_PROC proc ) {
1006 _response_dir_proc = proc;
1008 } /* end SetResponseDirectoryProc */
1010 /******************************************************************************/
1011 /******************************************************************************/
1012 /******************************************************************************/