summaryrefslogtreecommitdiffstats
path: root/private/nw/convert/nwconv/fcopy.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/nw/convert/nwconv/fcopy.c1162
1 files changed, 1162 insertions, 0 deletions
diff --git a/private/nw/convert/nwconv/fcopy.c b/private/nw/convert/nwconv/fcopy.c
new file mode 100644
index 000000000..6046ebad6
--- /dev/null
+++ b/private/nw/convert/nwconv/fcopy.c
@@ -0,0 +1,1162 @@
+/*++
+
+Copyright (c) 1993-1995 Microsoft Corporation
+
+Module Name:
+
+ FCopy.c
+
+Abstract:
+
+
+Author:
+
+ Arthur Hanson (arth) 16-Jun-1994
+
+Revision History:
+
+--*/
+
+
+#include "globals.h"
+
+#include <limits.h>
+
+#include "nwconv.h"
+#include "convapi.h"
+#include "ntnetapi.h"
+#include "nwnetapi.h"
+#include "userdlg.h"
+#include "statbox.h"
+#include "filedlg.h"
+
+//
+// Defines used in CopyNode routine - used for figuring out if we are doing
+// the home-directories in the MAIL sub-dir of the SYS vol.
+//
+#define DIR_TYPE_NORMAL 0
+#define DIR_TYPE_MAIL 1
+#define DIR_TYPE_LOGIN 2
+
+static TCHAR SourcePath[MAX_UNC_PATH];
+static LPTSTR spPtr;
+static FILE_OPTIONS *FileOptions = NULL;
+static CONVERT_OPTIONS *CurrentConvertOptions = NULL;
+static ULONG Count;
+static ULONG ServShareLen = 0;
+
+static USER_LIST *Users;
+static ULONG UserCount;
+static GROUP_LIST *Groups;
+static ULONG GroupCount;
+static BOOL IsNTFSDrive;
+
+static PSECURITY_DESCRIPTOR pSD = NULL;
+static PACL pACLNew = NULL;
+static PSID pSID = NULL;
+static ULONG CurSizeTotal;
+static ULONG CurNumFiles;
+static ULONG TotalSizeTotal;
+static BOOL SysRoot = FALSE;
+static BOOL SysVol = FALSE;
+
+extern UINT TotFiles;
+extern TCHAR UserServerName[];
+
+#define NWRIGHTSALL 0xFF
+
+#define BASE_16 16
+
+#define SWAPWORD(w) ((WORD)((w & 0xFF) << 8)|(WORD)(w >> 8))
+#define SWAPLONG(l) MAKELONG(SWAPWORD(HIWORD(l)),SWAPWORD(LOWORD(l)))
+
+
+TCHAR *fastcopy( HANDLE hfSrcParm, HANDLE hfDstParm );
+
+USER_BUFFER *FindUserMatch(LPTSTR Name, USER_LIST *UserList, BOOL NewName);
+GROUP_BUFFER *FindGroupMatch(LPTSTR Name, GROUP_LIST *GroupList, BOOL NewName);
+BOOL NTFile_AccessRightsAdd(LPTSTR ServerName, LPTSTR pUserName, LPTSTR pFileName, ULONG Rights, BOOL Dir);
+VOID ErrorIt(LPTSTR szFormat, ...);
+
+TCHAR SrcPath[MAX_UNC_PATH]; // +3 for slashes
+TCHAR DestPath[MAX_UNC_PATH]; // +3 for slashes
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+ConvertFilesInit(
+ HWND hDlg
+ )
+
+/*++
+
+Routine Description:
+
+ Initialization routine called before doing the file copying. Sets up
+ the information panel dialog and fills in the directory tree structures.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR NewPath[MAX_UNC_PATH];
+ SOURCE_SERVER_BUFFER *SServ;
+ DEST_SERVER_BUFFER *DServ;
+ SHARE_LIST *ShareList;
+ SHARE_BUFFER *SList;
+ SHARE_BUFFER *CurrentShare;
+ DRIVE_BUFFER *Drive;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ ULONG i;
+
+ // Just to be safe init this.
+ FillDirInit();
+ TotFiles = 0;
+ TotalSizeTotal = 0;
+
+ // Clear out old alloc space calculations
+ DServListSpaceFree();
+
+ CurrentConvertList = ConvertListStart;
+ while (CurrentConvertList) {
+ SServ = CurrentConvertList->SourceServ;
+ DServ = CurrentConvertList->FileServ;
+ ShareList = SServ->ShareList;
+
+ FileOptions = (FILE_OPTIONS *) CurrentConvertList->FileOptions;
+ if (FileOptions->TransferFileInfo) {
+ if (ShareList) {
+ SList = ShareList->SList;
+ // First expand all the file trees
+ for (i = 0; i < ShareList->Count; i++) {
+ CurrentShare = &SList[i];
+ if (CurrentShare->Convert) {
+ Panel_Line(1, Lids(IDS_D_1));
+ Panel_Line(6, TEXT("%s\\%s:"), SServ->Name, CurrentShare->Name);
+ Panel_Line(2, Lids(IDS_D_2));
+ Panel_Line(3, Lids(IDS_D_3));
+ Panel_Line(4, Lids(IDS_D_4));
+ wsprintf(NewPath, TEXT("\\\\%s\\%s\\"), SServ->Name, CurrentShare->Name);
+
+ if (CurrentShare->Root == NULL)
+ TreeRootInit(CurrentShare, NewPath);
+
+ TreeFillRecurse(1, NewPath, CurrentShare->Root);
+
+ // Now increment allocated space on dest drive
+ if (CurrentShare->DestShare != NULL)
+ if (CurrentShare->Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
+ Drive = VShare->Drive;
+
+ if (Drive != NULL)
+ Drive->AllocSpace += TotalFileSizeGet();
+
+ } else {
+ Drive = CurrentShare->DestShare->Drive;
+ if (Drive != NULL)
+ Drive->AllocSpace += TotalFileSizeGet();
+ }
+
+ }
+ } // expand the file trees...
+ }
+
+ } // if transfer files
+
+ CurrentConvertList = CurrentConvertList->next;
+ } // loop through servers
+
+} // ConvertFilesInit
+
+
+/////////////////////////////////////////////////////////////////////////
+PSECURITY_DESCRIPTOR
+SecurityDescriptorCreate(
+ LPTSTR ServerName
+ )
+
+/*++
+
+Routine Description:
+
+ Creates a security descriptor.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DWORD cbACL = 1024;
+ DWORD cbSID = 1024;
+ LPTSTR lpszAccount;
+ TCHAR lpszDomain[80];
+ DWORD cchDomainName = 80;
+ UCHAR psnuType[1024];
+ ACCESS_ALLOWED_ACE *pAAAce;
+
+ lpszAccount = Lids(IDS_S_1);
+
+ // Initialize a new security descriptor.
+ pSD = (PSECURITY_DESCRIPTOR) AllocMemory(SECURITY_DESCRIPTOR_MIN_LENGTH);
+ if (pSD == NULL)
+ return NULL;
+
+ if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) {
+ FreeMemory(pSD);
+ return NULL;
+ }
+
+ // Initialize a new ACL.
+ pACLNew = (PACL) AllocMemory(cbACL);
+ if (pACLNew == NULL) {
+ goto Cleanup;
+ }
+
+ if (!InitializeAcl(pACLNew, cbACL, ACL_REVISION2)) {
+ goto Cleanup;
+ }
+
+ // Retrieve the SID for UserABC.
+ pSID = (PSID) AllocMemory(cbSID);
+ if (pSID == NULL) {
+ goto Cleanup;
+ }
+
+ if (!LookupAccountName(ServerName, lpszAccount, pSID, &cbSID,
+ lpszDomain, &cchDomainName, (PSID_NAME_USE) psnuType)) {
+ goto Cleanup;
+ }
+
+ // Set access permissions
+ if (!AddAccessAllowedAce(pACLNew, ACL_REVISION2, GENERIC_ALL, pSID)) {
+ goto Cleanup;
+ }
+
+ if (!GetAce(pACLNew, 0, (LPVOID *) &pAAAce))
+ goto Cleanup;
+
+ pAAAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
+ pAAAce->Mask = GENERIC_ALL;
+
+ // Add a new ACL to the security descriptor.
+ if (!SetSecurityDescriptorDacl(pSD, TRUE, pACLNew, FALSE)) {
+ goto Cleanup;
+ }
+
+ return pSD;
+
+Cleanup:
+
+ if (pSID != NULL)
+ FreeSid(pSID);
+
+ if(pSD != NULL)
+ FreeMemory(pSD);
+
+ if(pACLNew != NULL)
+ FreeMemory(pACLNew);
+
+ return NULL;
+
+} // SecurityDescriptorCreate
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+MakeDir (
+ DEST_SERVER_BUFFER *DServ,
+ VIRTUAL_SHARE_BUFFER *VShare
+ )
+
+/*++
+
+Routine Description:
+
+ Given a path, this will start at the root of the path and create a
+ directory tree up to the ending node.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR NewPath[MAX_UNC_PATH];
+ TCHAR oc;
+ LPTSTR ptr;
+ TCHAR ServerName[MAX_SERVER_NAME_LEN + 3];
+ SECURITY_ATTRIBUTES sa;
+
+ // First need to construct a root path in the correct form
+ wsprintf(NewPath, TEXT("\\\\%s\\%s"), DServ->Name, VShare->Path);
+
+ ptr = NewPath;
+ if (*ptr == TEXT('\0'))
+ return;
+
+ // Look for ":" and change to the "$"
+ while (*ptr && *ptr != TEXT(':'))
+ ptr++;
+
+ if (*ptr == TEXT(':'))
+ *ptr = TEXT('$');
+ else
+ return;
+
+ // Go to initial backslash (one right after drive designator)
+ while (*ptr && *ptr != TEXT('\\'))
+ ptr++;
+
+ // We are pointing at the first char of the path - now loop through
+ // the path - looking for each backslash and make each sub-dir
+ // individually.
+ while (*ptr) {
+ // skip over backslash we are on
+ ptr++;
+
+ while (*ptr && *ptr != TEXT('\\'))
+ ptr++;
+
+ // sitting on next backslash - truncate path and make the dir
+ oc = *ptr;
+ *ptr = TEXT('\0');
+
+ wsprintf(ServerName, TEXT("\\\\%s"), DServ->Name);
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = SecurityDescriptorCreate(ServerName);
+ sa.bInheritHandle = TRUE;
+
+ CreateDirectory(NewPath, &sa);
+
+ // Now cleanup the allocated security stuff
+ if (pSID != NULL)
+ FreeSid(pSID);
+
+ if(pSD != NULL)
+ FreeMemory(pSD);
+
+ if(pACLNew != NULL)
+ FreeMemory(pACLNew);
+
+ *ptr = oc;
+ }
+
+} // MakeDir
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+VSharesCreate(
+ DEST_SERVER_BUFFER *DServ,
+ BOOL TConversion
+ )
+
+/*++
+
+Routine Description:
+
+ Given a virtual share struct, creates the share on the destination
+ server, include both an NT share and FPNW share if applicable. Will
+ also create any directories to point the share at if needed.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ CONVERT_OPTIONS *cvo;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ BOOL FPNWChk;
+
+ LogWriteLog(0, Lids(IDS_L_7));
+ VShare = CurrentConvertList->FileServ->VShareStart;
+ cvo = (CONVERT_OPTIONS *) CurrentConvertList->ConvertOptions;
+
+ FPNWChk = DServ->IsFPNW;
+
+ while (VShare) {
+ if (VShare->UseCount > 0) {
+ LogWriteLog(1, TEXT("%s \r\n"), VShare->Name);
+ LogWriteLog(2, Lids(IDS_L_8), VShare->Path);
+
+ if (!TConversion) {
+ MakeDir(DServ, VShare);
+ if ((cvo->NetWareInfo) && FPNWChk)
+ FPNWShareAdd(VShare->Name, VShare->Path);
+
+ NTShareAdd(VShare->Name, VShare->Path);
+ }
+
+ }
+
+ VShare = VShare->next;
+ }
+
+ LogWriteLog(0, Lids(IDS_CRLF));
+
+} // VSharesCreate
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+FileSecurityTransfer(
+ LPTSTR SrcPath,
+ LPTSTR DestPath,
+ BOOL TConversion,
+ BOOL Dir
+ )
+
+/*++
+
+Routine Description:
+
+ Given a source and destination path, will take all the file permissions
+ from the source and apply them to the destination. Will automatically
+ convert any user names to their new equivalence.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ BOOL match;
+ LPTSTR fnPtr;
+ USER_RIGHTS_LIST *secUsers = NULL;
+ ULONG secUserCount;
+ ULONG i;
+ USER_BUFFER *FoundUser;
+ GROUP_BUFFER *FoundGroup;
+ LPTSTR NewName;
+ ACCESS_MASK AccessMask;
+ NTSTATUS ntstatus;
+ BOOL DidEveryone = FALSE;
+
+ fnPtr = &SrcPath[ServShareLen];
+
+ lstrcat(SourcePath, fnPtr);
+ ErrorItemSet(Lids(IDS_L_9), SourcePath);
+
+#ifdef DEBUG
+dprintf(TEXT("Getting Rights for: %s\n"), SourcePath);
+#endif
+ if (!NWFileRightsEnum(SourcePath, &secUsers, &secUserCount, (CurrentConvertList->SourceServ->VerMaj < 3))) {
+
+ if (VerboseFileLogging() && (secUserCount > 0))
+ if (Dir)
+ LogWriteLog(2, Lids(IDS_L_10));
+ else
+ LogWriteLog(3, Lids(IDS_L_10));
+
+ for (i = 0; i < secUserCount; i++) {
+#ifdef DEBUG
+ dprintf(TEXT("%s %s\n"), NWRightsLog(secUsers[i].Rights), secUsers[i].Name);
+#endif
+
+ match = FALSE;
+ FoundUser = FindUserMatch(secUsers[i].Name, Users, FALSE);
+
+ // Check if this is "EVERYONE"
+ if (!lstrcmpi(secUsers[i].Name, Lids(IDS_S_31)))
+ DidEveryone = TRUE;
+
+ if (FoundUser == NULL) {
+ FoundGroup = FindGroupMatch(secUsers[i].Name, Groups, FALSE);
+ if (FoundGroup != NULL) {
+ match = TRUE;
+ NewName = FoundGroup->NewName;
+
+ }
+ } else {
+ match = TRUE;
+ NewName = FoundUser->NewName;
+ }
+
+ if (!match)
+ NewName = NWSpecialNamesMap(secUsers[i].Name);
+
+ // Map the NW rights to NT access mask
+ AccessMask = 0x0;
+
+ if (Dir)
+ ntstatus = MapNwRightsToNTAccess(secUsers[i].Rights, &DirRightsMapping, &AccessMask);
+ else
+ ntstatus = MapNwRightsToNTAccess(secUsers[i].Rights, &FileRightsMapping, &AccessMask);
+
+ if (VerboseFileLogging())
+ if (Dir)
+ LogWriteLog(3, TEXT("%s %-20s -> %-20s %s\r\n"), NWRightsLog(secUsers[i].Rights), secUsers[i].Name, NewName, NTAccessLog(AccessMask));
+ else
+ LogWriteLog(4, TEXT("%s %-20s -> %-20s %s\r\n"), NWRightsLog(secUsers[i].Rights), secUsers[i].Name, NewName, NTAccessLog(AccessMask));
+
+ if (NT_SUCCESS(ntstatus)) {
+#ifdef DEBUG
+dprintf(TEXT("Server: %s\n"), UserServerName);
+#endif
+ if (!TConversion)
+ NTFile_AccessRightsAdd(UserServerName, NewName, DestPath, AccessMask, Dir);
+ }
+#ifdef DEBUG
+ else
+ dprintf(TEXT("NwAddRight: MapNwRightsToNTAccess failed\n"));
+#endif
+ }
+
+ FreeMemory(secUsers);
+ }
+
+ //
+ // If this is the root of the sys vol, and the rights for Everyone weren't
+ // transferred, then Give everyone access. NT and NetWare handle
+ // permissions a bit differently. In NW if a user has permission
+ // nested down in a sub-dir, then NW will back-port S permission down
+ // to the root so the user can get access into the sub-dir. NT does
+ // access from the root up. Giving the user RX access provides a
+ // workaround.
+ //
+ if (SysRoot && !DidEveryone) {
+ // Use "Domain Users" for the user - equiv of everyone.
+ NewName = Lids(IDS_S_33);
+ // Map the NW rights to NT access mask
+ AccessMask = 0x0;
+
+ ntstatus = MapNwRightsToNTAccess(NW_FILE_READ, &DirRightsMapping, &AccessMask);
+
+ if (VerboseFileLogging())
+ LogWriteLog(3, TEXT("%s %-20s -> %-20s %s\r\n"), NWRightsLog(NW_FILE_READ), Lids(IDS_S_31), NewName, NTAccessLog(AccessMask));
+
+ if (NT_SUCCESS(ntstatus) && !TConversion)
+ NTFile_AccessRightsAdd(UserServerName, NewName, DestPath, AccessMask, Dir);
+ }
+
+ // re-truncate share name
+ *spPtr = TEXT('\0');
+
+} // FileSecurityTransfer
+
+
+/////////////////////////////////////////////////////////////////////////
+LPTSTR
+fcopy (
+ LPTSTR src,
+ LPTSTR dst
+ )
+
+/*++
+
+Routine Description:
+
+ fcopy (source file, destination file) copies the source to the destination
+ preserving attributes and filetimes. Returns NULL if OK or a char pointer
+ to the corresponding text of the error
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ static TCHAR fcopyErrorText[128];
+ HANDLE srcfh = INVALID_HANDLE_VALUE;
+ HANDLE dstfh = INVALID_HANDLE_VALUE;
+ LPTSTR result = NULL;
+ DWORD attribs;
+ FILETIME CreationTime, LastAccessTime, LastWriteTime;
+
+ attribs = GetFileAttributes(src);
+ if (attribs == FILE_ATTRIBUTE_DIRECTORY) {
+ result = Lids(IDS_L_11);
+ goto done;
+ }
+
+ if( ( srcfh = CreateFile( src, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ) ) == (HANDLE)-1 ) {
+ wsprintf( fcopyErrorText, Lids(IDS_L_12), GetLastError() );
+ result = fcopyErrorText;
+ goto done;
+ }
+
+ if (!GetFileTime(srcfh, &CreationTime, &LastAccessTime, &LastWriteTime)) {
+ result = Lids(IDS_L_13);
+ goto done;
+ }
+
+ if( ( dstfh = CreateFile( dst, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, srcfh ) ) == INVALID_HANDLE_VALUE) {
+ wsprintf( fcopyErrorText, Lids(IDS_L_14), GetLastError() );
+ result = fcopyErrorText;
+ goto done;
+ }
+
+ result = fastcopy( srcfh, dstfh );
+
+ if( result != NULL ) {
+ if (dstfh != INVALID_HANDLE_VALUE) {
+ CloseHandle( dstfh );
+ dstfh = INVALID_HANDLE_VALUE;
+ }
+
+ DeleteFile( dst );
+ goto done;
+ }
+
+ if (!SetFileTime(dstfh, &CreationTime, &LastAccessTime, &LastWriteTime)) {
+ result = Lids(IDS_L_15);
+ goto done;
+ }
+
+ if (attribs != 0xFFFFFFFF)
+ if (!SetFileAttributes(dst, attribs)) {
+ result = Lids(IDS_L_16);
+ goto done;
+ }
+
+done:
+ if (srcfh != INVALID_HANDLE_VALUE)
+ CloseHandle( srcfh );
+
+ if (dstfh != INVALID_HANDLE_VALUE)
+ CloseHandle( dstfh );
+
+ return result;
+} // fcopy
+
+
+/////////////////////////////////////////////////////////////////////////
+BOOL
+LoginDirConvert(
+ LPTSTR OldName,
+ LPTSTR NewName
+ )
+
+/*++
+
+Routine Description:
+
+ We need to copy login scripts, these reside in the mail directory on
+ the NetWare server. Each user's OBJECT_ID is a sub-directory. What
+ needs to be done is scan the sub-directories and convert the
+ OBJECT_ID for each user to the corresponding new OBJECT_ID on the
+ NT Server and rename the sub-dir to this new OBJECT_ID value. Then
+ copy the files.
+
+ The copy of the files and saving of the directory is done in
+ CopyNode, this routine converts the OBJECT-ID's.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DWORD OldID, NewID;
+ USER_BUFFER *FoundUser;
+ char aOldName[MAX_PATH + 1];
+ TCHAR OldUserName[MAX_PATH + 1];
+ LPTSTR NewUserName;
+ BOOL ret = TRUE;
+
+ //
+ // Need to take several conversion steps. We are passed in a string
+ // representation of the OBJECT-ID. This needs to be changed into
+ // the new string represenation of the new OBJECT-ID as follows:
+ //
+ // 1. Str-OBJECTID -> OBJECT-ID (DWORD)
+ // 2. OBJECT-ID -> Name (User Name on NW server)
+ // 3. Name -> New Name (on NT Server)
+ // 4. New Name -> OBJECT-ID (DWORD)
+ // 5. OBJECT-ID -> Str-OBJECTID
+ //
+
+ //
+ // Init just in case
+ //
+ lstrcpy(NewName, TEXT(""));
+ strcpy(aOldName, "");
+ OldID = NewID = 0;
+
+ //
+ // 1. Str-OBJECTID -> OBJECT-ID (DWORD)
+ //
+ WideCharToMultiByte(CP_ACP, 0, OldName, -1, aOldName, sizeof(aOldName), NULL, NULL);
+ RtlCharToInteger(aOldName, BASE_16, &OldID);
+ SWAPWORDS(OldID);
+
+ //
+ // If we didn't convert it, or not an Object ID, then use original string
+ //
+ if (OldID == 0) {
+ lstrcpy(NewName, OldName);
+ ret = FALSE;
+ goto LoginDirConvertExit;
+ }
+
+ //
+ // 2. OBJECT-ID -> Name (User Name on NW server)
+ //
+ if (!NWObjectNameGet(OldID, OldUserName)) {
+ lstrcpy(NewName, OldName);
+ ret = FALSE;
+ goto LoginDirConvertExit;
+ }
+
+ //
+ // 3. Name -> New Name (on NT Server)
+ //
+ FoundUser = FindUserMatch(OldUserName, Users, FALSE);
+ NewUserName = OldUserName;
+
+ if (FoundUser != NULL)
+ NewUserName = FoundUser->NewName;
+
+ //
+ // 4. New Name -> OBJECT-ID (DWORD)
+ //
+ NewID = NTObjectIDGet(NewUserName);
+
+ if (NewID == 0) {
+ lstrcpy(NewName, OldName);
+ ret = FALSE;
+ goto LoginDirConvertExit;
+ }
+
+ //
+ // 5. OBJECT-ID -> Str-OBJECTID
+ //
+ wsprintf(NewName, TEXT("%lX"), MAKELONG(HIWORD(NewID),SWAPWORD(LOWORD(NewID))) );
+
+LoginDirConvertExit:
+#ifdef DEBUG
+ if (ret)
+ dprintf(TEXT("Converting Login Dir for [%s]: %s -> %s\n"), OldUserName, OldName, NewName);
+#endif
+
+ return ret;
+
+} // LoginDirConvert
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+CopyNode(
+ DIR_BUFFER *Dir,
+ BOOL First,
+ BOOL TConversion,
+ DWORD DirType
+ )
+
+/*++
+
+Routine Description:
+
+ A node in this case is a sub-directory. This is a recursive function that
+ will copy all files and sub-directories under a given sub-directory.
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ LPTSTR ErrText;
+ DIR_LIST *DirList = NULL;
+ FILE_LIST *FileList = NULL;
+ DIR_BUFFER *DList;
+ FILE_BUFFER *FList;
+ LPTSTR pSrcPath, pDestPath;
+ TCHAR Attributes[10];
+ ULONG i;
+ DWORD ChildDirType;
+ DWORD attribs;
+
+ if (Dir == NULL)
+ return;
+
+ if (!Dir->Convert)
+ return;
+
+ SysRoot = FALSE;
+
+ // 1. Make dir if need be.
+ // 2. Copy all files in this dir
+ // 3. For each sub-dir recurse into this function, building up the path
+
+ //
+ // 1. Make Dir
+ //
+ if (!First) {
+ lstrcat(SrcPath, Dir->Name);
+
+ //
+ // If a HOME directory, then we need to convert the name to the new
+ // USER-ID
+ //
+ if (DirType == DIR_TYPE_LOGIN) {
+ TCHAR NewDirName[MAX_PATH + 1];
+
+ if (!LoginDirConvert(Dir->Name, NewDirName))
+ return;
+
+ lstrcat(DestPath, NewDirName);
+ } else
+ lstrcat(DestPath, Dir->Name);
+
+ if (!TConversion) {
+ attribs = GetFileAttributes(SrcPath);
+ CreateDirectory(DestPath, NULL);
+
+ if (attribs != 0xFFFFFFFF)
+ SetFileAttributes(DestPath, attribs);
+ }
+
+ } else {
+ lstrcat(DestPath, TEXT("\\"));
+
+ // Check if this is the root of the sys dir (for special security transfer).
+ if (SysVol)
+ SysRoot = TRUE;
+ }
+
+ if (VerboseFileLogging()) {
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(2, Lids(IDS_L_17), SrcPath);
+ LogWriteLog(2, Lids(IDS_L_18), DestPath);
+ }
+
+ if (IsNTFSDrive)
+ FileSecurityTransfer(SrcPath, DestPath, TConversion, TRUE);
+
+ // No need for this anymore
+ SysRoot = FALSE;
+
+ // Fixup and remember our path
+ lstrcat(SrcPath, TEXT("\\"));
+
+ if (!First)
+ lstrcat(DestPath, TEXT("\\"));
+
+ Status_ItemLabel(Lids(IDS_L_19), NicePath(50, SrcPath));
+
+ // Remember where end of source and dest paths are - so we don't have to
+ // store them on the stack all the time
+ pSrcPath = SrcPath;
+ while (*pSrcPath)
+ pSrcPath++;
+
+ pDestPath = DestPath;
+ while (*pDestPath)
+ pDestPath++;
+
+ Status_CurNum((UINT) Count+1);
+
+ //
+ // 2. Copy All Files in this dir
+ //
+ FileList = Dir->FileList;
+ if (FileList) {
+
+ if (FileList->Count > 0)
+ LogWriteLog(2, Lids(IDS_L_20));
+
+ FList = FileList->FileBuffer;
+ for (i = 0; i < FileList->Count; i++)
+ if (FList[i].Convert) {
+ ErrText = NULL;
+ lstrcat(SrcPath, FList[i].Name);
+ lstrcat(DestPath, FList[i].Name);
+ Status_CurNum((UINT) Count+1);
+#ifdef DEBUG
+dprintf(TEXT("FC: %s -> %s\n"), SrcPath, DestPath);
+#endif
+ ErrorItemSet(Lids(IDS_L_19), SrcPath);
+ Status_Item(FList[i].Name);
+ TotFiles++;
+ CurNumFiles++;
+ Status_TotFiles(TotFiles);
+ Count++;
+
+ Status_TotBytes(lToStr(FList[i].Size));
+
+ if (!TConversion) {
+ ErrText = fcopy(SrcPath, DestPath);
+
+ if (IsNTFSDrive)
+ FileSecurityTransfer(SrcPath, DestPath, TConversion, FALSE);
+ }
+
+ if (VerboseFileLogging()) {
+ lstrcpy(Attributes, Lids(IDS_L_21));
+ if (!(FList[i].Attributes & FILE_ATTRIBUTE_READONLY))
+ Attributes[1] = TEXT(' ');
+
+ if (!(FList[i].Attributes & FILE_ATTRIBUTE_ARCHIVE))
+ Attributes[2] = TEXT(' ');
+
+ if (!(FList[i].Attributes & FILE_ATTRIBUTE_HIDDEN))
+ Attributes[3] = TEXT(' ');
+
+ if (!(FList[i].Attributes & FILE_ATTRIBUTE_SYSTEM))
+ Attributes[4] = TEXT(' ');
+
+ LogWriteLog(3, TEXT("%13s %s %s\r\n"), lToStr(FList[i].Size), Attributes, FList[i].Name);
+ }
+
+ if (ErrText != NULL) {
+ if (!VerboseFileLogging())
+ LogWriteLog(3, Lids(IDS_L_22), SrcPath, DestPath);
+
+ LogWriteLog(4, TEXT("%s\r\n"), ErrText);
+ ErrorIt(TEXT("%s\r\n"), ErrText);
+ } else {
+ CurSizeTotal += FList[i].Size;
+ TotalSizeTotal += FList[i].Size;
+ }
+
+ // reset our paths to the right place
+ *pSrcPath = TEXT('\0');
+ *pDestPath = TEXT('\0');
+ }
+
+ }
+
+ //
+ // 3. Recurse the sub-dirs
+ //
+ DirList = Dir->DirList;
+ if (DirList) {
+ DList = DirList->DirBuffer;
+ for (i = 0; i < DirList->Count; i++)
+ if (DList[i].Convert) {
+
+ //
+ // Reset child dir type...
+ //
+ ChildDirType = DIR_TYPE_NORMAL;
+
+ //
+ // If this is the mail sub-dir, then the children are home-dirs
+ //
+ if (DirType == DIR_TYPE_MAIL)
+ ChildDirType = DIR_TYPE_LOGIN;
+
+ // recurse into this dir - check if this is the mail dir
+ if (SysVol && First && !lstrcmpi(DList[i].Name, TEXT("MAIL")) && CurrentConvertList->FileServ->IsFPNW )
+ ChildDirType = DIR_TYPE_MAIL;
+
+ CopyNode(&DList[i], FALSE, TConversion, ChildDirType);
+
+ // reset our paths to the right place
+ *pSrcPath = TEXT('\0');
+ *pDestPath = TEXT('\0');
+ }
+ } // Recursing Sub-dirs
+
+} // CopyNode
+
+
+/////////////////////////////////////////////////////////////////////////
+VOID
+ConvertFiles(
+ HWND hDlg,
+ BOOL TConversion,
+ USER_LIST *iUsers,
+ GROUP_LIST *iGroups
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+
+{
+ DIR_LIST *DirList = NULL;
+ SOURCE_SERVER_BUFFER *SServ;
+ DEST_SERVER_BUFFER *DServ;
+ VIRTUAL_SHARE_BUFFER *VShare;
+ SHARE_LIST *ShareList;
+ SHARE_BUFFER *SList;
+ SHARE_BUFFER *CurrentShare;
+ ULONG i;
+
+ Users = iUsers;
+ Groups = iGroups;
+
+ if (iUsers != NULL)
+ UserCount = iUsers->Count;
+ else
+ UserCount = 0;
+
+ if (iGroups != NULL)
+ GroupCount = iGroups->Count;
+ else
+ GroupCount = 0;
+
+ Count = 0;
+ FileOptions = (FILE_OPTIONS *) CurrentConvertList->FileOptions;
+ CurrentConvertOptions = (CONVERT_OPTIONS *) CurrentConvertList->ConvertOptions;
+ SServ = CurrentConvertList->SourceServ;
+ DServ = CurrentConvertList->FileServ;
+
+ // Synchronize the domain
+ NTDomainSynch(DServ);
+
+ // Following steps are taken:
+ // 1. Enumerate / create all virtual shares
+ // 2. Enumerate volumes and destinations to convert
+ // 3. Go to each volume - copy that tree
+
+ ShareList = SServ->ShareList;
+
+ if (VerboseFileLogging()) {
+ LogWriteLog(0, Lids(IDS_LINE));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_23));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_24));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_25));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_26));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_27));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_28));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_29));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_30));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_31));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_32));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_33));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_34));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_35));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_36));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_37));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_38));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_39));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_40));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_41));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_42));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_43));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_44));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_45));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_46));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_47));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_48));
+ LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_49));
+ LogWriteLog(0, Lids(IDS_LINE));
+ }
+
+ LogWriteLog(0, Lids(IDS_L_20));
+ Status_ConvTxt(Lids(IDS_L_50));
+ Status_ItemLabel(Lids(IDS_L_51));
+
+ if (ShareList) {
+ SList = ShareList->SList;
+
+ for (i = 0; i < ShareList->Count; i++) {
+ Count = 0;
+ CurrentShare = &SList[i];
+ if (CurrentShare->Root)
+ Status_CurTot((UINT) TreeCount(CurrentShare->Root));
+
+ if (CurrentShare->Convert) {
+ // Set root paths for this conversion
+ memset(SrcPath, 0, sizeof(SrcPath));
+ wsprintf(SrcPath, TEXT("\\\\%s\\%s"), SServ->Name, CurrentShare->Name);
+ ServShareLen = lstrlen(SrcPath) + 1;
+
+ // create sharename for access rights query in form of "SHARE:"
+ memset(SourcePath, 0, sizeof(SourcePath));
+ lstrcpy(SourcePath, CurrentShare->Name);
+ lstrcat(SourcePath, TEXT(":"));
+
+ // Check if this is the root of the sys dir (for special security transfer).
+ SysVol = FALSE;
+ if (!lstrcmpi(CurrentShare->Name, Lids(IDS_S_6)))
+ SysVol = TRUE;
+
+ // point spPtr to ending NULL so we can truncate it back
+ spPtr = &SourcePath[lstrlen(SourcePath)];
+ LogWriteSummary(0, Lids(IDS_CRLF));
+ LogWriteLog(0, Lids(IDS_CRLF));
+ LogWriteLog(1, Lids(IDS_L_52), CurrentShare->Name);
+ LogWriteSummary(1, Lids(IDS_L_52), CurrentShare->Name);
+
+ if (CurrentShare->Virtual) {
+ VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
+ //
+ // NOTE: The DestShare->Name may be that of the ncp server so
+ // instead of formatting the destination \\server\share\<foo>,
+ // which means nothing to the smb server if the share is fpnw,
+ // we format the destination \\server\d$\path\<foo>.
+ //
+ wsprintf(DestPath, TEXT("\\\\%s\\%s"), DServ->Name, VShare->Path);
+ DestPath[2+lstrlen(DServ->Name)+1+1] = TEXT('$'); // replace ':' with '$' in unc path
+
+ if (VShare->Drive != NULL)
+ IsNTFSDrive = (VShare->Drive->Type == DRIVE_TYPE_NTFS);
+ else
+ IsNTFSDrive = FALSE;
+
+ LogWriteLog(1, Lids(IDS_L_53), VShare->Name);
+ LogWriteSummary(1, Lids(IDS_L_53), VShare->Name);
+ } else {
+ //
+ // NOTE: The DestShare->Name may be that of the ncp server so
+ // instead of formatting the destination \\server\share\<foo>,
+ // which means nothing to the smb server if the share is fpnw,
+ // we format the destination \\server\d$\path\<foo>.
+ //
+ wsprintf(DestPath, TEXT("\\\\%s\\%s"), DServ->Name, CurrentShare->DestShare->Path);
+ DestPath[2+lstrlen(DServ->Name)+1+1] = TEXT('$'); // replace ':' with '$' in unc path
+
+ if (CurrentShare->DestShare->Drive != NULL)
+ IsNTFSDrive = (CurrentShare->DestShare->Drive->Type == DRIVE_TYPE_NTFS);
+ else
+ IsNTFSDrive = FALSE;
+
+ LogWriteLog(1, Lids(IDS_L_53), CurrentShare->DestShare->Name);
+ LogWriteSummary(1, Lids(IDS_L_53), CurrentShare->DestShare->Name);
+ }
+
+ CurSizeTotal = 0;
+ CurNumFiles = 0;
+ CopyNode(CurrentShare->Root, TRUE, TConversion, (DWORD) DIR_TYPE_NORMAL);
+ LogWriteSummary(2, Lids(IDS_L_54), lToStr(CurNumFiles));
+ LogWriteSummary(2, Lids(IDS_L_55), lToStr(CurSizeTotal));
+
+ // Whack it down to minimum size to conserve memory
+ TreePrune(CurrentShare->Root);
+ }
+ }
+ }
+
+} // ConvertFiles