Source code of Windows XP (NT5)
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

  1. /*++
  2. Copyright (c) 1993-1995 Microsoft Corporation
  3. Module Name:
  4. FCopy.c
  5. Abstract:
  6. Author:
  7. Arthur Hanson (arth) 16-Jun-1994
  8. Revision History:
  9. --*/
  10. #include "globals.h"
  11. #include <limits.h>
  12. #include "nwconv.h"
  13. #include "convapi.h"
  14. #include "ntnetapi.h"
  15. #include "nwnetapi.h"
  16. #include "userdlg.h"
  17. #include "statbox.h"
  18. #include "filedlg.h"
  19. //
  20. // Defines used in CopyNode routine - used for figuring out if we are doing
  21. // the home-directories in the MAIL sub-dir of the SYS vol.
  22. //
  23. #define DIR_TYPE_NORMAL 0
  24. #define DIR_TYPE_MAIL 1
  25. #define DIR_TYPE_LOGIN 2
  26. static TCHAR SourcePath[MAX_UNC_PATH];
  27. static LPTSTR spPtr;
  28. static FILE_OPTIONS *FileOptions = NULL;
  29. static CONVERT_OPTIONS *CurrentConvertOptions = NULL;
  30. static ULONG Count;
  31. static ULONG ServShareLen = 0;
  32. static USER_LIST *Users;
  33. static ULONG UserCount;
  34. static GROUP_LIST *Groups;
  35. static ULONG GroupCount;
  36. static BOOL IsNTFSDrive;
  37. static PSECURITY_DESCRIPTOR pSD = NULL;
  38. static PACL pACLNew = NULL;
  39. static PSID pSID = NULL;
  40. static ULONG CurSizeTotal;
  41. static ULONG CurNumFiles;
  42. static ULONG TotalSizeTotal;
  43. static BOOL SysRoot = FALSE;
  44. static BOOL SysVol = FALSE;
  45. extern UINT TotFiles;
  46. extern TCHAR UserServerName[];
  47. #define NWRIGHTSALL 0xFF
  48. #define BASE_16 16
  49. #define SWAPWORD(w) ((WORD)((w & 0xFF) << 8)|(WORD)(w >> 8))
  50. #define SWAPLONG(l) MAKELONG(SWAPWORD(HIWORD(l)),SWAPWORD(LOWORD(l)))
  51. TCHAR *fastcopy( HANDLE hfSrcParm, HANDLE hfDstParm );
  52. USER_BUFFER *FindUserMatch(LPTSTR Name, USER_LIST *UserList, BOOL NewName);
  53. GROUP_BUFFER *FindGroupMatch(LPTSTR Name, GROUP_LIST *GroupList, BOOL NewName);
  54. BOOL NTFile_AccessRightsAdd(LPTSTR ServerName, LPTSTR pUserName, LPTSTR pFileName, ULONG Rights, BOOL Dir);
  55. VOID ErrorIt(LPTSTR szFormat, ...);
  56. TCHAR SrcPath[MAX_UNC_PATH]; // +3 for slashes
  57. TCHAR DestPath[MAX_UNC_PATH]; // +3 for slashes
  58. /////////////////////////////////////////////////////////////////////////
  59. VOID
  60. ConvertFilesInit(
  61. HWND hDlg
  62. )
  63. /*++
  64. Routine Description:
  65. Initialization routine called before doing the file copying. Sets up
  66. the information panel dialog and fills in the directory tree structures.
  67. Arguments:
  68. Return Value:
  69. --*/
  70. {
  71. static TCHAR NewPath[MAX_UNC_PATH];
  72. SOURCE_SERVER_BUFFER *SServ;
  73. DEST_SERVER_BUFFER *DServ;
  74. SHARE_LIST *ShareList;
  75. SHARE_BUFFER *SList;
  76. SHARE_BUFFER *CurrentShare;
  77. DRIVE_BUFFER *Drive;
  78. VIRTUAL_SHARE_BUFFER *VShare;
  79. ULONG i;
  80. // Just to be safe init this.
  81. FillDirInit();
  82. TotFiles = 0;
  83. TotalSizeTotal = 0;
  84. // Clear out old alloc space calculations
  85. DServListSpaceFree();
  86. CurrentConvertList = ConvertListStart;
  87. while (CurrentConvertList) {
  88. SServ = CurrentConvertList->SourceServ;
  89. DServ = CurrentConvertList->FileServ;
  90. ShareList = SServ->ShareList;
  91. FileOptions = (FILE_OPTIONS *) CurrentConvertList->FileOptions;
  92. if (FileOptions->TransferFileInfo) {
  93. if (ShareList) {
  94. SList = ShareList->SList;
  95. // First expand all the file trees
  96. for (i = 0; i < ShareList->Count; i++) {
  97. CurrentShare = &SList[i];
  98. if (CurrentShare->Convert) {
  99. Panel_Line(1, Lids(IDS_D_1));
  100. Panel_Line(6, TEXT("%s\\%s:"), SServ->Name, CurrentShare->Name);
  101. Panel_Line(2, Lids(IDS_D_2));
  102. Panel_Line(3, Lids(IDS_D_3));
  103. Panel_Line(4, Lids(IDS_D_4));
  104. wsprintf(NewPath, TEXT("\\\\%s\\%s\\"), SServ->Name, CurrentShare->Name);
  105. if (CurrentShare->Root == NULL)
  106. TreeRootInit(CurrentShare, NewPath);
  107. TreeFillRecurse(1, NewPath, CurrentShare->Root);
  108. // Now increment allocated space on dest drive
  109. if (CurrentShare->DestShare != NULL)
  110. if (CurrentShare->Virtual) {
  111. VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
  112. Drive = VShare->Drive;
  113. if (Drive != NULL)
  114. Drive->AllocSpace += TotalFileSizeGet();
  115. } else {
  116. Drive = CurrentShare->DestShare->Drive;
  117. if (Drive != NULL)
  118. Drive->AllocSpace += TotalFileSizeGet();
  119. }
  120. }
  121. } // expand the file trees...
  122. }
  123. } // if transfer files
  124. CurrentConvertList = CurrentConvertList->next;
  125. } // loop through servers
  126. } // ConvertFilesInit
  127. /////////////////////////////////////////////////////////////////////////
  128. PSECURITY_DESCRIPTOR
  129. SecurityDescriptorCreate(
  130. LPTSTR ServerName
  131. )
  132. /*++
  133. Routine Description:
  134. Creates a security descriptor.
  135. Arguments:
  136. Return Value:
  137. --*/
  138. {
  139. DWORD cbACL = 1024;
  140. DWORD cbSID = 1024;
  141. LPTSTR lpszAccount;
  142. TCHAR lpszDomain[80];
  143. DWORD cchDomainName = 80;
  144. UCHAR psnuType[1024];
  145. ACCESS_ALLOWED_ACE *pAAAce;
  146. lpszAccount = Lids(IDS_S_1);
  147. // Initialize a new security descriptor.
  148. pSD = (PSECURITY_DESCRIPTOR) AllocMemory(SECURITY_DESCRIPTOR_MIN_LENGTH);
  149. if (pSD == NULL)
  150. return NULL;
  151. if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) {
  152. FreeMemory(pSD);
  153. return NULL;
  154. }
  155. // Initialize a new ACL.
  156. pACLNew = (PACL) AllocMemory(cbACL);
  157. if (pACLNew == NULL) {
  158. goto Cleanup;
  159. }
  160. if (!InitializeAcl(pACLNew, cbACL, ACL_REVISION2)) {
  161. goto Cleanup;
  162. }
  163. // Retrieve the SID for UserABC.
  164. pSID = (PSID) AllocMemory(cbSID);
  165. if (pSID == NULL) {
  166. goto Cleanup;
  167. }
  168. if (!LookupAccountName(ServerName, lpszAccount, pSID, &cbSID,
  169. lpszDomain, &cchDomainName, (PSID_NAME_USE) psnuType)) {
  170. goto Cleanup;
  171. }
  172. // Set access permissions
  173. if (!AddAccessAllowedAce(pACLNew, ACL_REVISION2, GENERIC_ALL, pSID)) {
  174. goto Cleanup;
  175. }
  176. if (!GetAce(pACLNew, 0, (LPVOID *) &pAAAce))
  177. goto Cleanup;
  178. pAAAce->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  179. pAAAce->Mask = GENERIC_ALL;
  180. // Add a new ACL to the security descriptor.
  181. if (!SetSecurityDescriptorDacl(pSD, TRUE, pACLNew, FALSE)) {
  182. goto Cleanup;
  183. }
  184. return pSD;
  185. Cleanup:
  186. if (pSID != NULL)
  187. FreeSid(pSID);
  188. if(pSD != NULL)
  189. FreeMemory(pSD);
  190. if(pACLNew != NULL)
  191. FreeMemory(pACLNew);
  192. return NULL;
  193. } // SecurityDescriptorCreate
  194. /////////////////////////////////////////////////////////////////////////
  195. VOID
  196. MakeDir (
  197. DEST_SERVER_BUFFER *DServ,
  198. VIRTUAL_SHARE_BUFFER *VShare
  199. )
  200. /*++
  201. Routine Description:
  202. Given a path, this will start at the root of the path and create a
  203. directory tree up to the ending node.
  204. Arguments:
  205. Return Value:
  206. --*/
  207. {
  208. static TCHAR NewPath[MAX_UNC_PATH];
  209. TCHAR oc;
  210. LPTSTR ptr;
  211. TCHAR ServerName[MAX_SERVER_NAME_LEN + 3];
  212. SECURITY_ATTRIBUTES sa;
  213. // First need to construct a root path in the correct form
  214. wsprintf(NewPath, TEXT("\\\\%s\\%s"), DServ->Name, VShare->Path);
  215. ptr = NewPath;
  216. if (*ptr == TEXT('\0'))
  217. return;
  218. // Look for ":" and change to the "$"
  219. while (*ptr && *ptr != TEXT(':'))
  220. ptr++;
  221. if (*ptr == TEXT(':'))
  222. *ptr = TEXT('$');
  223. else
  224. return;
  225. // Go to initial backslash (one right after drive designator)
  226. while (*ptr && *ptr != TEXT('\\'))
  227. ptr++;
  228. // We are pointing at the first char of the path - now loop through
  229. // the path - looking for each backslash and make each sub-dir
  230. // individually.
  231. while (*ptr) {
  232. // skip over backslash we are on
  233. ptr++;
  234. while (*ptr && *ptr != TEXT('\\'))
  235. ptr++;
  236. // sitting on next backslash - truncate path and make the dir
  237. oc = *ptr;
  238. *ptr = TEXT('\0');
  239. wsprintf(ServerName, TEXT("\\\\%s"), DServ->Name);
  240. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  241. sa.lpSecurityDescriptor = SecurityDescriptorCreate(ServerName);
  242. sa.bInheritHandle = TRUE;
  243. CreateDirectory(NewPath, &sa);
  244. // Now cleanup the allocated security stuff
  245. if (pSID != NULL)
  246. FreeSid(pSID);
  247. if(pSD != NULL)
  248. FreeMemory(pSD);
  249. if(pACLNew != NULL)
  250. FreeMemory(pACLNew);
  251. *ptr = oc;
  252. }
  253. } // MakeDir
  254. /////////////////////////////////////////////////////////////////////////
  255. VOID
  256. VSharesCreate(
  257. DEST_SERVER_BUFFER *DServ,
  258. BOOL TConversion
  259. )
  260. /*++
  261. Routine Description:
  262. Given a virtual share struct, creates the share on the destination
  263. server, include both an NT share and FPNW share if applicable. Will
  264. also create any directories to point the share at if needed.
  265. Arguments:
  266. Return Value:
  267. --*/
  268. {
  269. CONVERT_OPTIONS *cvo;
  270. VIRTUAL_SHARE_BUFFER *VShare;
  271. BOOL FPNWChk;
  272. LogWriteLog(0, Lids(IDS_L_7));
  273. VShare = CurrentConvertList->FileServ->VShareStart;
  274. cvo = (CONVERT_OPTIONS *) CurrentConvertList->ConvertOptions;
  275. FPNWChk = DServ->IsFPNW;
  276. while (VShare) {
  277. if (VShare->UseCount > 0) {
  278. LogWriteLog(1, TEXT("%s \r\n"), VShare->Name);
  279. LogWriteLog(2, Lids(IDS_L_8), VShare->Path);
  280. if (!TConversion) {
  281. MakeDir(DServ, VShare);
  282. if ((cvo->NetWareInfo) && FPNWChk)
  283. FPNWShareAdd(VShare->Name, VShare->Path);
  284. NTShareAdd(VShare->Name, VShare->Path);
  285. }
  286. }
  287. VShare = VShare->next;
  288. }
  289. LogWriteLog(0, Lids(IDS_CRLF));
  290. } // VSharesCreate
  291. /////////////////////////////////////////////////////////////////////////
  292. VOID
  293. FileSecurityTransfer(
  294. LPTSTR SrcPath,
  295. LPTSTR DestPath,
  296. BOOL TConversion,
  297. BOOL Dir
  298. )
  299. /*++
  300. Routine Description:
  301. Given a source and destination path, will take all the file permissions
  302. from the source and apply them to the destination. Will automatically
  303. convert any user names to their new equivalence.
  304. Arguments:
  305. Return Value:
  306. --*/
  307. {
  308. BOOL match;
  309. LPTSTR fnPtr;
  310. USER_RIGHTS_LIST *secUsers = NULL;
  311. ULONG secUserCount;
  312. ULONG i;
  313. USER_BUFFER *FoundUser;
  314. GROUP_BUFFER *FoundGroup;
  315. LPTSTR NewName;
  316. ACCESS_MASK AccessMask;
  317. NTSTATUS ntstatus;
  318. BOOL DidEveryone = FALSE;
  319. fnPtr = &SrcPath[ServShareLen];
  320. lstrcat(SourcePath, fnPtr);
  321. ErrorItemSet(Lids(IDS_L_9), SourcePath);
  322. #ifdef DEBUG
  323. dprintf(TEXT("Getting Rights for: %s\n"), SourcePath);
  324. #endif
  325. if (!NWFileRightsEnum(SourcePath, &secUsers, &secUserCount, (CurrentConvertList->SourceServ->VerMaj < 3))) {
  326. if (VerboseFileLogging() && (secUserCount > 0))
  327. if (Dir)
  328. LogWriteLog(2, Lids(IDS_L_10));
  329. else
  330. LogWriteLog(3, Lids(IDS_L_10));
  331. for (i = 0; i < secUserCount; i++) {
  332. #ifdef DEBUG
  333. dprintf(TEXT("%s %s\n"), NWRightsLog(secUsers[i].Rights), secUsers[i].Name);
  334. #endif
  335. match = FALSE;
  336. FoundUser = FindUserMatch(secUsers[i].Name, Users, FALSE);
  337. // Check if this is "EVERYONE"
  338. if (!lstrcmpi(secUsers[i].Name, Lids(IDS_S_31)))
  339. DidEveryone = TRUE;
  340. if (FoundUser == NULL) {
  341. FoundGroup = FindGroupMatch(secUsers[i].Name, Groups, FALSE);
  342. if (FoundGroup != NULL) {
  343. match = TRUE;
  344. NewName = FoundGroup->NewName;
  345. }
  346. } else {
  347. match = TRUE;
  348. NewName = FoundUser->NewName;
  349. }
  350. if (!match)
  351. NewName = NWSpecialNamesMap(secUsers[i].Name);
  352. // Map the NW rights to NT access mask
  353. AccessMask = 0x0;
  354. if (Dir)
  355. ntstatus = MapNwRightsToNTAccess(secUsers[i].Rights, &DirRightsMapping, &AccessMask);
  356. else
  357. ntstatus = MapNwRightsToNTAccess(secUsers[i].Rights, &FileRightsMapping, &AccessMask);
  358. if (VerboseFileLogging())
  359. if (Dir)
  360. LogWriteLog(3, TEXT("%s %-20s -> %-20s %s\r\n"), NWRightsLog(secUsers[i].Rights), secUsers[i].Name, NewName, NTAccessLog(AccessMask));
  361. else
  362. LogWriteLog(4, TEXT("%s %-20s -> %-20s %s\r\n"), NWRightsLog(secUsers[i].Rights), secUsers[i].Name, NewName, NTAccessLog(AccessMask));
  363. if (NT_SUCCESS(ntstatus)) {
  364. #ifdef DEBUG
  365. dprintf(TEXT("Server: %s\n"), UserServerName);
  366. #endif
  367. if (!TConversion)
  368. NTFile_AccessRightsAdd(UserServerName, NewName, DestPath, AccessMask, Dir);
  369. }
  370. #ifdef DEBUG
  371. else
  372. dprintf(TEXT("NwAddRight: MapNwRightsToNTAccess failed\n"));
  373. #endif
  374. }
  375. FreeMemory(secUsers);
  376. }
  377. //
  378. // If this is the root of the sys vol, and the rights for Everyone weren't
  379. // transferred, then Give everyone access. NT and NetWare handle
  380. // permissions a bit differently. In NW if a user has permission
  381. // nested down in a sub-dir, then NW will back-port S permission down
  382. // to the root so the user can get access into the sub-dir. NT does
  383. // access from the root up. Giving the user RX access provides a
  384. // workaround.
  385. //
  386. if (SysRoot && !DidEveryone) {
  387. // Use "Domain Users" for the user - equiv of everyone.
  388. NewName = Lids(IDS_S_33);
  389. // Map the NW rights to NT access mask
  390. AccessMask = 0x0;
  391. ntstatus = MapNwRightsToNTAccess(NW_FILE_READ, &DirRightsMapping, &AccessMask);
  392. if (VerboseFileLogging())
  393. LogWriteLog(3, TEXT("%s %-20s -> %-20s %s\r\n"), NWRightsLog(NW_FILE_READ), Lids(IDS_S_31), NewName, NTAccessLog(AccessMask));
  394. if (NT_SUCCESS(ntstatus) && !TConversion)
  395. NTFile_AccessRightsAdd(UserServerName, NewName, DestPath, AccessMask, Dir);
  396. }
  397. // re-truncate share name
  398. *spPtr = TEXT('\0');
  399. } // FileSecurityTransfer
  400. /////////////////////////////////////////////////////////////////////////
  401. LPTSTR
  402. fcopy (
  403. LPTSTR src,
  404. LPTSTR dst
  405. )
  406. /*++
  407. Routine Description:
  408. fcopy (source file, destination file) copies the source to the destination
  409. preserving attributes and filetimes. Returns NULL if OK or a char pointer
  410. to the corresponding text of the error
  411. Arguments:
  412. Return Value:
  413. --*/
  414. {
  415. static TCHAR fcopyErrorText[128];
  416. HANDLE srcfh = INVALID_HANDLE_VALUE;
  417. HANDLE dstfh = INVALID_HANDLE_VALUE;
  418. LPTSTR result = NULL;
  419. DWORD attribs;
  420. FILETIME CreationTime, LastAccessTime, LastWriteTime;
  421. attribs = GetFileAttributes(src);
  422. if (attribs == FILE_ATTRIBUTE_DIRECTORY) {
  423. result = Lids(IDS_L_11);
  424. goto done;
  425. }
  426. if( ( srcfh = CreateFile( src, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ) ) == (HANDLE)-1 ) {
  427. wsprintf( fcopyErrorText, Lids(IDS_L_12), GetLastError() );
  428. result = fcopyErrorText;
  429. goto done;
  430. }
  431. if (!GetFileTime(srcfh, &CreationTime, &LastAccessTime, &LastWriteTime)) {
  432. result = Lids(IDS_L_13);
  433. goto done;
  434. }
  435. if( ( dstfh = CreateFile( dst, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, srcfh ) ) == INVALID_HANDLE_VALUE) {
  436. wsprintf( fcopyErrorText, Lids(IDS_L_14), GetLastError() );
  437. result = fcopyErrorText;
  438. goto done;
  439. }
  440. result = fastcopy( srcfh, dstfh );
  441. if( result != NULL ) {
  442. if (dstfh != INVALID_HANDLE_VALUE) {
  443. CloseHandle( dstfh );
  444. dstfh = INVALID_HANDLE_VALUE;
  445. }
  446. DeleteFile( dst );
  447. goto done;
  448. }
  449. if (!SetFileTime(dstfh, &CreationTime, &LastAccessTime, &LastWriteTime)) {
  450. result = Lids(IDS_L_15);
  451. goto done;
  452. }
  453. if (attribs != 0xFFFFFFFF)
  454. if (!SetFileAttributes(dst, attribs)) {
  455. result = Lids(IDS_L_16);
  456. goto done;
  457. }
  458. done:
  459. if (srcfh != INVALID_HANDLE_VALUE)
  460. CloseHandle( srcfh );
  461. if (dstfh != INVALID_HANDLE_VALUE)
  462. CloseHandle( dstfh );
  463. return result;
  464. } // fcopy
  465. /////////////////////////////////////////////////////////////////////////
  466. BOOL
  467. LoginDirConvert(
  468. LPTSTR OldName,
  469. LPTSTR NewName
  470. )
  471. /*++
  472. Routine Description:
  473. We need to copy login scripts, these reside in the mail directory on
  474. the NetWare server. Each user's OBJECT_ID is a sub-directory. What
  475. needs to be done is scan the sub-directories and convert the
  476. OBJECT_ID for each user to the corresponding new OBJECT_ID on the
  477. NT Server and rename the sub-dir to this new OBJECT_ID value. Then
  478. copy the files.
  479. The copy of the files and saving of the directory is done in
  480. CopyNode, this routine converts the OBJECT-ID's.
  481. Arguments:
  482. Return Value:
  483. --*/
  484. {
  485. DWORD OldID, NewID;
  486. USER_BUFFER *FoundUser;
  487. char aOldName[MAX_PATH + 1];
  488. TCHAR OldUserName[MAX_PATH + 1];
  489. LPTSTR NewUserName;
  490. BOOL ret = TRUE;
  491. //
  492. // Need to take several conversion steps. We are passed in a string
  493. // representation of the OBJECT-ID. This needs to be changed into
  494. // the new string represenation of the new OBJECT-ID as follows:
  495. //
  496. // 1. Str-OBJECTID -> OBJECT-ID (DWORD)
  497. // 2. OBJECT-ID -> Name (User Name on NW server)
  498. // 3. Name -> New Name (on NT Server)
  499. // 4. New Name -> OBJECT-ID (DWORD)
  500. // 5. OBJECT-ID -> Str-OBJECTID
  501. //
  502. //
  503. // Init just in case
  504. //
  505. lstrcpy(NewName, TEXT(""));
  506. strcpy(aOldName, "");
  507. OldID = NewID = 0;
  508. //
  509. // 1. Str-OBJECTID -> OBJECT-ID (DWORD)
  510. //
  511. WideCharToMultiByte(CP_ACP, 0, OldName, -1, aOldName, sizeof(aOldName), NULL, NULL);
  512. RtlCharToInteger(aOldName, BASE_16, &OldID);
  513. SWAPWORDS(OldID);
  514. //
  515. // If we didn't convert it, or not an Object ID, then use original string
  516. //
  517. if (OldID == 0) {
  518. lstrcpy(NewName, OldName);
  519. ret = FALSE;
  520. goto LoginDirConvertExit;
  521. }
  522. //
  523. // 2. OBJECT-ID -> Name (User Name on NW server)
  524. //
  525. if (!NWObjectNameGet(OldID, OldUserName)) {
  526. lstrcpy(NewName, OldName);
  527. ret = FALSE;
  528. goto LoginDirConvertExit;
  529. }
  530. //
  531. // 3. Name -> New Name (on NT Server)
  532. //
  533. FoundUser = FindUserMatch(OldUserName, Users, FALSE);
  534. NewUserName = OldUserName;
  535. if (FoundUser != NULL)
  536. NewUserName = FoundUser->NewName;
  537. //
  538. // 4. New Name -> OBJECT-ID (DWORD)
  539. //
  540. NewID = NTObjectIDGet(NewUserName);
  541. if (NewID == 0) {
  542. lstrcpy(NewName, OldName);
  543. ret = FALSE;
  544. goto LoginDirConvertExit;
  545. }
  546. //
  547. // 5. OBJECT-ID -> Str-OBJECTID
  548. //
  549. wsprintf(NewName, TEXT("%lX"), MAKELONG(HIWORD(NewID),SWAPWORD(LOWORD(NewID))) );
  550. LoginDirConvertExit:
  551. #ifdef DEBUG
  552. if (ret)
  553. dprintf(TEXT("Converting Login Dir for [%s]: %s -> %s\n"), OldUserName, OldName, NewName);
  554. #endif
  555. return ret;
  556. } // LoginDirConvert
  557. /////////////////////////////////////////////////////////////////////////
  558. VOID
  559. CopyNode(
  560. DIR_BUFFER *Dir,
  561. BOOL First,
  562. BOOL TConversion,
  563. DWORD DirType
  564. )
  565. /*++
  566. Routine Description:
  567. A node in this case is a sub-directory. This is a recursive function that
  568. will copy all files and sub-directories under a given sub-directory.
  569. Arguments:
  570. Return Value:
  571. --*/
  572. {
  573. LPTSTR ErrText;
  574. DIR_LIST *DirList = NULL;
  575. FILE_LIST *FileList = NULL;
  576. DIR_BUFFER *DList;
  577. FILE_BUFFER *FList;
  578. LPTSTR pSrcPath, pDestPath;
  579. TCHAR Attributes[10];
  580. ULONG i;
  581. DWORD ChildDirType;
  582. DWORD attribs;
  583. if (Dir == NULL)
  584. return;
  585. if (!Dir->Convert)
  586. return;
  587. SysRoot = FALSE;
  588. // 1. Make dir if need be.
  589. // 2. Copy all files in this dir
  590. // 3. For each sub-dir recurse into this function, building up the path
  591. //
  592. // 1. Make Dir
  593. //
  594. if (!First) {
  595. lstrcat(SrcPath, Dir->Name);
  596. //
  597. // If a HOME directory, then we need to convert the name to the new
  598. // USER-ID
  599. //
  600. if (DirType == DIR_TYPE_LOGIN) {
  601. TCHAR NewDirName[MAX_PATH + 1];
  602. if (!LoginDirConvert(Dir->Name, NewDirName))
  603. return;
  604. lstrcat(DestPath, NewDirName);
  605. } else
  606. lstrcat(DestPath, Dir->Name);
  607. if (!TConversion) {
  608. attribs = GetFileAttributes(SrcPath);
  609. CreateDirectory(DestPath, NULL);
  610. if (attribs != 0xFFFFFFFF)
  611. SetFileAttributes(DestPath, attribs);
  612. }
  613. } else {
  614. lstrcat(DestPath, TEXT("\\"));
  615. // Check if this is the root of the sys dir (for special security transfer).
  616. if (SysVol)
  617. SysRoot = TRUE;
  618. }
  619. if (VerboseFileLogging()) {
  620. LogWriteLog(0, Lids(IDS_CRLF));
  621. LogWriteLog(2, Lids(IDS_L_17), SrcPath);
  622. LogWriteLog(2, Lids(IDS_L_18), DestPath);
  623. }
  624. if (IsNTFSDrive)
  625. FileSecurityTransfer(SrcPath, DestPath, TConversion, TRUE);
  626. // No need for this anymore
  627. SysRoot = FALSE;
  628. // Fixup and remember our path
  629. lstrcat(SrcPath, TEXT("\\"));
  630. if (!First)
  631. lstrcat(DestPath, TEXT("\\"));
  632. Status_ItemLabel(Lids(IDS_L_19), NicePath(50, SrcPath));
  633. // Remember where end of source and dest paths are - so we don't have to
  634. // store them on the stack all the time
  635. pSrcPath = SrcPath;
  636. while (*pSrcPath)
  637. pSrcPath++;
  638. pDestPath = DestPath;
  639. while (*pDestPath)
  640. pDestPath++;
  641. Status_CurNum((UINT) Count+1);
  642. //
  643. // 2. Copy All Files in this dir
  644. //
  645. FileList = Dir->FileList;
  646. if (FileList) {
  647. if (FileList->Count > 0)
  648. LogWriteLog(2, Lids(IDS_L_20));
  649. FList = FileList->FileBuffer;
  650. for (i = 0; i < FileList->Count; i++)
  651. if (FList[i].Convert) {
  652. ErrText = NULL;
  653. lstrcat(SrcPath, FList[i].Name);
  654. lstrcat(DestPath, FList[i].Name);
  655. Status_CurNum((UINT) Count+1);
  656. #ifdef DEBUG
  657. dprintf(TEXT("FC: %s -> %s\n"), SrcPath, DestPath);
  658. #endif
  659. ErrorItemSet(Lids(IDS_L_19), SrcPath);
  660. Status_Item(FList[i].Name);
  661. TotFiles++;
  662. CurNumFiles++;
  663. Status_TotFiles(TotFiles);
  664. Count++;
  665. Status_TotBytes(lToStr(FList[i].Size));
  666. if (!TConversion) {
  667. ErrText = fcopy(SrcPath, DestPath);
  668. if (IsNTFSDrive)
  669. FileSecurityTransfer(SrcPath, DestPath, TConversion, FALSE);
  670. }
  671. if (VerboseFileLogging()) {
  672. lstrcpy(Attributes, Lids(IDS_L_21));
  673. if (!(FList[i].Attributes & FILE_ATTRIBUTE_READONLY))
  674. Attributes[1] = TEXT(' ');
  675. if (!(FList[i].Attributes & FILE_ATTRIBUTE_ARCHIVE))
  676. Attributes[2] = TEXT(' ');
  677. if (!(FList[i].Attributes & FILE_ATTRIBUTE_HIDDEN))
  678. Attributes[3] = TEXT(' ');
  679. if (!(FList[i].Attributes & FILE_ATTRIBUTE_SYSTEM))
  680. Attributes[4] = TEXT(' ');
  681. LogWriteLog(3, TEXT("%13s %s %s\r\n"), lToStr(FList[i].Size), Attributes, FList[i].Name);
  682. }
  683. if (ErrText != NULL) {
  684. if (!VerboseFileLogging())
  685. LogWriteLog(3, Lids(IDS_L_22), SrcPath, DestPath);
  686. LogWriteLog(4, TEXT("%s\r\n"), ErrText);
  687. ErrorIt(TEXT("%s\r\n"), ErrText);
  688. } else {
  689. CurSizeTotal += FList[i].Size;
  690. TotalSizeTotal += FList[i].Size;
  691. }
  692. // reset our paths to the right place
  693. *pSrcPath = TEXT('\0');
  694. *pDestPath = TEXT('\0');
  695. }
  696. }
  697. //
  698. // 3. Recurse the sub-dirs
  699. //
  700. DirList = Dir->DirList;
  701. if (DirList) {
  702. DList = DirList->DirBuffer;
  703. for (i = 0; i < DirList->Count; i++)
  704. if (DList[i].Convert) {
  705. //
  706. // Reset child dir type...
  707. //
  708. ChildDirType = DIR_TYPE_NORMAL;
  709. //
  710. // If this is the mail sub-dir, then the children are home-dirs
  711. //
  712. if (DirType == DIR_TYPE_MAIL)
  713. ChildDirType = DIR_TYPE_LOGIN;
  714. // recurse into this dir - check if this is the mail dir
  715. if (SysVol && First && !lstrcmpi(DList[i].Name, TEXT("MAIL")) && CurrentConvertList->FileServ->IsFPNW )
  716. ChildDirType = DIR_TYPE_MAIL;
  717. CopyNode(&DList[i], FALSE, TConversion, ChildDirType);
  718. // reset our paths to the right place
  719. *pSrcPath = TEXT('\0');
  720. *pDestPath = TEXT('\0');
  721. }
  722. } // Recursing Sub-dirs
  723. } // CopyNode
  724. /////////////////////////////////////////////////////////////////////////
  725. VOID
  726. ConvertFiles(
  727. HWND hDlg,
  728. BOOL TConversion,
  729. USER_LIST *iUsers,
  730. GROUP_LIST *iGroups
  731. )
  732. /*++
  733. Routine Description:
  734. Arguments:
  735. Return Value:
  736. --*/
  737. {
  738. DIR_LIST *DirList = NULL;
  739. SOURCE_SERVER_BUFFER *SServ;
  740. DEST_SERVER_BUFFER *DServ;
  741. VIRTUAL_SHARE_BUFFER *VShare;
  742. SHARE_LIST *ShareList;
  743. SHARE_BUFFER *SList;
  744. SHARE_BUFFER *CurrentShare;
  745. ULONG i;
  746. Users = iUsers;
  747. Groups = iGroups;
  748. if (iUsers != NULL)
  749. UserCount = iUsers->Count;
  750. else
  751. UserCount = 0;
  752. if (iGroups != NULL)
  753. GroupCount = iGroups->Count;
  754. else
  755. GroupCount = 0;
  756. Count = 0;
  757. FileOptions = (FILE_OPTIONS *) CurrentConvertList->FileOptions;
  758. CurrentConvertOptions = (CONVERT_OPTIONS *) CurrentConvertList->ConvertOptions;
  759. SServ = CurrentConvertList->SourceServ;
  760. DServ = CurrentConvertList->FileServ;
  761. // Synchronize the domain
  762. NTDomainSynch(DServ);
  763. // Following steps are taken:
  764. // 1. Enumerate / create all virtual shares
  765. // 2. Enumerate volumes and destinations to convert
  766. // 3. Go to each volume - copy that tree
  767. ShareList = SServ->ShareList;
  768. if (VerboseFileLogging()) {
  769. LogWriteLog(0, Lids(IDS_LINE));
  770. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_23));
  771. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_24));
  772. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_25));
  773. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_26));
  774. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_27));
  775. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_28));
  776. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_29));
  777. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_30));
  778. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_31));
  779. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_32));
  780. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_33));
  781. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_34));
  782. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_35));
  783. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_36));
  784. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_37));
  785. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_38));
  786. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_39));
  787. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_40));
  788. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_41));
  789. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_42));
  790. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_43));
  791. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_44));
  792. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_45));
  793. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_46));
  794. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_47));
  795. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_48));
  796. LogWriteLog(0, Lids(IDS_BRACE), Lids(IDS_L_49));
  797. LogWriteLog(0, Lids(IDS_LINE));
  798. }
  799. LogWriteLog(0, Lids(IDS_L_20));
  800. Status_ConvTxt(Lids(IDS_L_50));
  801. Status_ItemLabel(Lids(IDS_L_51));
  802. if (ShareList) {
  803. SList = ShareList->SList;
  804. for (i = 0; i < ShareList->Count; i++) {
  805. Count = 0;
  806. CurrentShare = &SList[i];
  807. if (CurrentShare->Root)
  808. Status_CurTot((UINT) TreeCount(CurrentShare->Root));
  809. if (CurrentShare->Convert) {
  810. // Set root paths for this conversion
  811. memset(SrcPath, 0, sizeof(SrcPath));
  812. wsprintf(SrcPath, TEXT("\\\\%s\\%s"), SServ->Name, CurrentShare->Name);
  813. ServShareLen = lstrlen(SrcPath) + 1;
  814. // create sharename for access rights query in form of "SHARE:"
  815. memset(SourcePath, 0, sizeof(SourcePath));
  816. lstrcpy(SourcePath, CurrentShare->Name);
  817. lstrcat(SourcePath, TEXT(":"));
  818. // Check if this is the root of the sys dir (for special security transfer).
  819. SysVol = FALSE;
  820. if (!lstrcmpi(CurrentShare->Name, Lids(IDS_S_6)))
  821. SysVol = TRUE;
  822. // point spPtr to ending NULL so we can truncate it back
  823. spPtr = &SourcePath[lstrlen(SourcePath)];
  824. LogWriteSummary(0, Lids(IDS_CRLF));
  825. LogWriteLog(0, Lids(IDS_CRLF));
  826. LogWriteLog(1, Lids(IDS_L_52), CurrentShare->Name);
  827. LogWriteSummary(1, Lids(IDS_L_52), CurrentShare->Name);
  828. if (CurrentShare->Virtual) {
  829. VShare = (VIRTUAL_SHARE_BUFFER *) CurrentShare->DestShare;
  830. //
  831. // NOTE: The DestShare->Name may be that of the ncp server so
  832. // instead of formatting the destination \\server\share\<foo>,
  833. // which means nothing to the smb server if the share is fpnw,
  834. // we format the destination \\server\d$\path\<foo>.
  835. //
  836. wsprintf(DestPath, TEXT("\\\\%s\\%s"), DServ->Name, VShare->Path);
  837. DestPath[2+lstrlen(DServ->Name)+1+1] = TEXT('$'); // replace ':' with '$' in unc path
  838. if (VShare->Drive != NULL)
  839. IsNTFSDrive = (VShare->Drive->Type == DRIVE_TYPE_NTFS);
  840. else
  841. IsNTFSDrive = FALSE;
  842. LogWriteLog(1, Lids(IDS_L_53), VShare->Name);
  843. LogWriteSummary(1, Lids(IDS_L_53), VShare->Name);
  844. } else {
  845. //
  846. // NOTE: The DestShare->Name may be that of the ncp server so
  847. // instead of formatting the destination \\server\share\<foo>,
  848. // which means nothing to the smb server if the share is fpnw,
  849. // we format the destination \\server\d$\path\<foo>.
  850. //
  851. wsprintf(DestPath, TEXT("\\\\%s\\%s"), DServ->Name, CurrentShare->DestShare->Path);
  852. DestPath[2+lstrlen(DServ->Name)+1+1] = TEXT('$'); // replace ':' with '$' in unc path
  853. if (CurrentShare->DestShare->Drive != NULL)
  854. IsNTFSDrive = (CurrentShare->DestShare->Drive->Type == DRIVE_TYPE_NTFS);
  855. else
  856. IsNTFSDrive = FALSE;
  857. LogWriteLog(1, Lids(IDS_L_53), CurrentShare->DestShare->Name);
  858. LogWriteSummary(1, Lids(IDS_L_53), CurrentShare->DestShare->Name);
  859. }
  860. CurSizeTotal = 0;
  861. CurNumFiles = 0;
  862. CopyNode(CurrentShare->Root, TRUE, TConversion, (DWORD) DIR_TYPE_NORMAL);
  863. LogWriteSummary(2, Lids(IDS_L_54), lToStr(CurNumFiles));
  864. LogWriteSummary(2, Lids(IDS_L_55), lToStr(CurSizeTotal));
  865. // Whack it down to minimum size to conserve memory
  866. TreePrune(CurrentShare->Root);
  867. }
  868. }
  869. }
  870. } // ConvertFiles