mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1162 lines
30 KiB
1162 lines
30 KiB
/*++
|
|
|
|
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
|