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.

868 lines
29 KiB

  1. //#pragma title( "SDResolve.cpp - SDResolve: A Domain Migration Utility" )
  2. /*
  3. Copyright (c) 1995-1998, Mission Critical Software, Inc. All rights reserved.
  4. ===============================================================================
  5. Module - sdresolve.cpp
  6. System - SDResolve
  7. Author - Christy Boles
  8. Created - 97/07/11
  9. Description - Routines to iterate through files, shares, and printers
  10. when processing security on a machine.
  11. Updates -
  12. ===============================================================================
  13. */
  14. #include "stdafx.h"
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <iostream.h>
  18. #include <fstream.h>
  19. #include <assert.h>
  20. #include "Common.hpp"
  21. #include "ErrDct.hpp"
  22. #include "UString.hpp"
  23. #include "sd.hpp"
  24. #include "sidcache.hpp"
  25. #include "enumvols.hpp"
  26. #include "SecObj.hpp"
  27. #include "ealen.hpp"
  28. #include "BkupRstr.hpp"
  29. #include "TxtSid.h"
  30. #ifdef _DEBUG
  31. #define new DEBUG_NEW
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. bool enforce;
  36. extern TErrorDct err;
  37. extern bool silent;
  38. extern bool IsMachineName(const LPWSTR name);
  39. extern bool IsShareName(const LPWSTR name);
  40. extern bool ContainsWildcard( WCHAR const * name);
  41. #define MAX_BUFFER_LENGTH 10000
  42. #define PRINT_BUFFER_SIZE 2000
  43. //******************************************************************************************************
  44. // Main routine for SDResolve
  45. // Iterates files and directories to be resolved
  46. void
  47. IteratePath(
  48. WCHAR * path, // in -path to start iterating from
  49. SecurityTranslatorArgs * args, // in -translation settings
  50. TSDResolveStats * stats, // in -stats (to display pathnames & pass to ResolveSD)
  51. TSecurableObject * LC, // in -last container
  52. TSecurableObject * LL, // in -last file
  53. bool haswc // in -indicates whether path contains a wc character
  54. )
  55. {
  56. HANDLE hFind;
  57. WIN32_FIND_DATA findEntry;
  58. BOOL b;
  59. TFileSD * currSD;
  60. bool changeLastCont;
  61. bool changeLastLeaf;
  62. WCHAR * appendPath = NULL;
  63. WCHAR safepath[LEN_Path + 10];
  64. TFileSD * LastContain = (TFileSD*) LC;
  65. TFileSD * LastLeaf = (TFileSD*) LL;
  66. WCHAR localPath[LEN_Path];
  67. // this is the first (for this) dir
  68. safecopy(safepath,path);
  69. safecopy(localPath,path);
  70. // Check to see if path is longer than MAX_PATH
  71. // if so, add \\?\ to the beginning of it to
  72. // turn off path parsing
  73. if ( UStrLen(path) >= MAX_PATH && path[2] != L'?' )
  74. {
  75. WCHAR temp[LEN_Path];
  76. if ( (path[0] == L'\\') && (path[1] == L'\\') ) // UNC name
  77. {
  78. UStrCpy(temp,L"\\\\?\\UNC\\");
  79. }
  80. else
  81. {
  82. UStrCpy(temp,L"\\\\?\\");
  83. }
  84. UStrCpy(temp + UStrLen(temp),path);
  85. safecopy(localPath,temp);
  86. }
  87. appendPath = localPath + UStrLen(localPath);
  88. if ( *(appendPath-1) == L'\\' ) // if there's already a backslash on the end of the path, don't add another one
  89. appendPath--;
  90. if ( ! haswc )
  91. UStrCpy(appendPath, "\\*.*");
  92. if ( args->LogVerbose() )
  93. err.DbgMsgWrite(0,L"Starting IteratePath: %ls",path);
  94. for ( b = ((hFind = FindFirstFile(localPath, &findEntry)) != INVALID_HANDLE_VALUE)
  95. ; b ; b = FindNextFile(hFind, &findEntry) )
  96. {
  97. if ( ! haswc)
  98. appendPath[1] = '\0'; // restore path -- remove \*.* append
  99. if ( ! UStrCmp((LPWSTR)findEntry.cFileName,L".") || ! UStrCmp((LPWSTR)findEntry.cFileName,L"..") )
  100. continue; // ignore names '.' and '..'
  101. if ( ! haswc )
  102. UStrCpy(appendPath+1, findEntry.cFileName);
  103. else
  104. {
  105. for ( WCHAR * ch = appendPath-1; ch >= path && *ch != L'\\' ; ch-- )
  106. ;
  107. UStrCpy(ch+1,findEntry.cFileName);
  108. }
  109. if ( ((TAccountCache *)args->Cache())->IsCancelled() )
  110. {
  111. break;
  112. }
  113. currSD = new TFileSD(localPath);
  114. stats->DisplayPath(localPath);
  115. if ( !currSD || !currSD->HasSecurity() )
  116. {
  117. //err.MsgWrite(0,"Error: Couldn't get the SD");
  118. }
  119. else
  120. {
  121. if ( findEntry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) // if dir
  122. {
  123. // resolve this container & iterate next container
  124. changeLastCont = currSD->ResolveSD(args,stats,directory,LastContain);
  125. if ( changeLastCont )
  126. {
  127. if ( LastContain && LastContain != LC )
  128. {
  129. delete LastContain;
  130. }
  131. LastContain = currSD;
  132. }
  133. else
  134. {
  135. delete currSD;
  136. }
  137. IteratePath(localPath,args,stats,LastContain,LastLeaf,false);
  138. }
  139. else
  140. {
  141. // iterate this file with last
  142. changeLastLeaf = currSD->ResolveSD(args,stats,file,LastLeaf);
  143. if ( changeLastLeaf )
  144. {
  145. if ( LastLeaf && LastLeaf != LL )
  146. {
  147. delete LastLeaf;
  148. }
  149. LastLeaf = currSD;
  150. }
  151. else
  152. {
  153. delete currSD;
  154. }
  155. }
  156. }
  157. }
  158. if ( LastContain && LastContain != LC )
  159. {
  160. delete LastContain;
  161. }
  162. if ( LastLeaf && LastLeaf != LL )
  163. {
  164. delete LastLeaf;
  165. }
  166. appendPath[0] = '\0';
  167. DWORD rc = GetLastError();
  168. if ( args->LogVerbose() )
  169. err.DbgMsgWrite(0,L"Closing IteratePath %S",safepath);
  170. FindClose(hFind);
  171. switch ( rc )
  172. {
  173. case ERROR_NO_MORE_FILES:
  174. case 0:
  175. break;
  176. default:
  177. err.SysMsgWrite(ErrE, rc, DCT_MSG_FIND_FILE_FAILED_SD, path, rc);
  178. }
  179. return;
  180. }
  181. DWORD
  182. ResolvePrinter(
  183. PRINTER_INFO_4 * pPrinter, // in - printer information
  184. SecurityTranslatorArgs * args, // in - translation settings
  185. TSDResolveStats * stats // in - stats
  186. )
  187. {
  188. DWORD rc = 0;
  189. // DWORD needed = 0;
  190. TPrintSD sd(pPrinter->pPrinterName);
  191. if ( sd.GetSecurity() )
  192. {
  193. sd.ResolveSD(args,stats,printer,NULL);
  194. }
  195. return rc;
  196. }
  197. int
  198. ServerResolvePrinters(
  199. WCHAR const * server, // in -translate the printers on this server
  200. SecurityTranslatorArgs * args, // in -translation settings
  201. TSDResolveStats * stats // in -stats
  202. )
  203. {
  204. DWORD rc = 0;
  205. PRINTER_INFO_4 * pInfo = NULL;
  206. BYTE * buffer = new BYTE[PRINT_BUFFER_SIZE];
  207. DWORD cbNeeded = PRINT_BUFFER_SIZE;
  208. DWORD nReturned = 0;
  209. if (!buffer)
  210. return ERROR_NOT_ENOUGH_MEMORY;
  211. if (! EnumPrinters(PRINTER_ENUM_LOCAL,NULL,4,buffer,PRINT_BUFFER_SIZE,&cbNeeded,&nReturned) )
  212. {
  213. rc = GetLastError();
  214. if ( rc == ERROR_INSUFFICIENT_BUFFER )
  215. {
  216. // try again with a bigger buffer size
  217. delete buffer;
  218. buffer = new BYTE[cbNeeded];
  219. if (!buffer)
  220. return ERROR_NOT_ENOUGH_MEMORY;
  221. if (! EnumPrinters(PRINTER_ENUM_LOCAL,NULL,4,buffer,cbNeeded,&cbNeeded,&nReturned) )
  222. {
  223. rc = GetLastError();
  224. }
  225. }
  226. }
  227. if ( ! rc )
  228. {
  229. pInfo = (PRINTER_INFO_4 *)buffer;
  230. for ( DWORD i = 0 ; i < nReturned ; i++ )
  231. {
  232. ResolvePrinter(&(pInfo[i]),args,stats);
  233. }
  234. }
  235. else
  236. {
  237. err.SysMsgWrite(ErrE,rc,DCT_MSG_ERROR_ENUMERATING_LOCAL_PRINTERS_D,rc);
  238. }
  239. delete buffer;
  240. return rc;
  241. }
  242. int
  243. ServerResolveShares(
  244. WCHAR const * server, // in -enumerate and translate the shares on this server
  245. SecurityTranslatorArgs * args, // in -translation settings
  246. TSDResolveStats * stats // in -stats (to display pathnames & pass to ResolveSD)
  247. )
  248. {
  249. DWORD rc = 0;
  250. DWORD numRead = 0;
  251. DWORD totalEntries = 0;
  252. DWORD resumeHandle = 0;
  253. SHARE_INFO_0 * bufPtr = NULL;
  254. WCHAR serverName[LEN_Computer];
  255. WCHAR fullPath[LEN_Path];
  256. WCHAR * pServerName = serverName;
  257. DWORD ttlRead = 0;
  258. if ( server )
  259. {
  260. safecopy(serverName,server);
  261. }
  262. else
  263. {
  264. pServerName = NULL;
  265. }
  266. do
  267. {
  268. rc = NetShareEnum(pServerName,0,(LPBYTE *)&bufPtr,MAX_BUFFER_LENGTH,&numRead,&totalEntries,&resumeHandle);
  269. if ( ! rc || rc == ERROR_MORE_DATA )
  270. {
  271. for ( UINT i = 0 ; i < numRead ; i++ )
  272. {
  273. // Process the SD
  274. if ( pServerName )
  275. {
  276. swprintf(fullPath,L"%s\\%s",pServerName,bufPtr[i].shi0_netname);
  277. }
  278. else
  279. {
  280. swprintf(fullPath,L"%s",bufPtr[i].shi0_netname);
  281. }
  282. TShareSD tSD(fullPath);
  283. if ( tSD.HasSecurity() )
  284. {
  285. stats->DisplayPath(fullPath,TRUE);
  286. tSD.ResolveSD(args,stats,share,NULL);
  287. }
  288. }
  289. ttlRead += numRead;
  290. resumeHandle = ttlRead;
  291. NetApiBufferFree(bufPtr);
  292. }
  293. } while ( rc == ERROR_MORE_DATA && numRead < totalEntries );
  294. if ( rc && rc != ERROR_MORE_DATA )
  295. err.SysMsgWrite(ErrE,rc,DCT_MSG_SHARE_ENUM_FAILED_SD,server,rc);
  296. return rc;
  297. }
  298. void
  299. ResolveFilePath(
  300. SecurityTranslatorArgs * args, // in - translation options
  301. TSDResolveStats * Stats, // in - class to display stats
  302. WCHAR * path, // in - path name
  303. bool validAlone, // in - whether this object exists (false for share names and volume roots)
  304. bool containsWC, // in - true if path contains wildcard
  305. bool iscontainer // in - whether the starting path is a container
  306. )
  307. {
  308. TFileSD * pSD;
  309. if ( args->LogVerbose() )
  310. err.MsgWrite(0,DCT_MSG_PROCESSING_S,path);
  311. Stats->DisplayPath(path);
  312. if ( validAlone && ! containsWC )
  313. {
  314. pSD = new TFileSD(path);
  315. if (!pSD)
  316. return;
  317. if ( pSD->HasSecurity() )
  318. pSD->ResolveSD(args,
  319. Stats,
  320. iscontainer?directory:file,
  321. NULL);
  322. delete pSD;
  323. }
  324. if ( iscontainer || containsWC )
  325. {
  326. IteratePath(path,
  327. args,
  328. Stats,
  329. NULL,
  330. NULL,
  331. containsWC);
  332. }
  333. if ( args->Cache()->IsCancelled() )
  334. {
  335. err.MsgWrite(0,DCT_MSG_OPERATION_ABORTED);
  336. }
  337. }
  338. void WriteOptions(SecurityTranslatorArgs * args)
  339. {
  340. //* WCHAR cmd[1000] = L"SecurityTranslation ";;
  341. WCHAR cmd[1000];
  342. WCHAR arg[300];
  343. UStrCpy(cmd, GET_STRING(IDS_STOptions_Start));
  344. if ( args->NoChange() )
  345. {
  346. //* UStrCpy(cmd +UStrLen(cmd), L"WriteChanges:No ");
  347. UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_WriteChng));
  348. }
  349. if ( args->TranslateFiles() )
  350. {
  351. //* UStrCpy(cmd +UStrLen(cmd), L"Files:Yes ");
  352. UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_Files));
  353. }
  354. if ( args->TranslateShares() )
  355. {
  356. //* UStrCpy(cmd + UStrLen(cmd),L"Shares:Yes ");
  357. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_Shares));
  358. }
  359. if ( args->TranslateLocalGroups() )
  360. {
  361. //* UStrCpy(cmd + UStrLen(cmd),L"LGroups:Yes ");
  362. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_LocalGroup));
  363. }
  364. if ( args->TranslateUserRights() )
  365. {
  366. // UStrCpy(cmd + UStrLen(cmd),L"UserRights:Yes ");
  367. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_URights));
  368. }
  369. if ( args->TranslatePrinters() )
  370. {
  371. // UStrCpy(cmd + UStrLen(cmd),L"UserRights:Yes ");
  372. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_Printers));
  373. }
  374. if ( args->TranslateUserProfiles() )
  375. {
  376. //* UStrCpy(cmd + UStrLen(cmd),L"Profiles:Yes ");
  377. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_Profiles));
  378. }
  379. if ( args->TranslateRecycler() )
  380. {
  381. //* UStrCpy(cmd + UStrLen(cmd),L"RecycleBin:Yes ");
  382. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_RBin));
  383. }
  384. if ( *args->LogFile() )
  385. {
  386. //* wsprintf(arg,L"LogFile:%S ",args->LogFile());
  387. wsprintf(arg,GET_STRING(IDS_STOptions_LogName),args->LogFile());
  388. UStrCpy(cmd +UStrLen(cmd), arg);
  389. }
  390. if ( args->TranslationMode() == ADD_SECURITY )
  391. {
  392. //* UStrCpy(cmd +UStrLen(cmd), L"TranslationMode:Add ");
  393. UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_AddMode));
  394. }
  395. else if ( args->TranslationMode() == REMOVE_SECURITY )
  396. {
  397. //* UStrCpy(cmd +UStrLen(cmd), L"TranslationMode:Remove ");
  398. UStrCpy(cmd +UStrLen(cmd), GET_STRING(IDS_STOptions_RemoveMode));
  399. }
  400. else
  401. {
  402. //* UStrCpy(cmd + UStrLen(cmd),L"TranslationMode:Replace ");
  403. UStrCpy(cmd + UStrLen(cmd),GET_STRING(IDS_STOptions_ReplaceMode));
  404. }
  405. wsprintf(arg,L"%s %s ",args->Source(), args->Target());
  406. UStrCpy(cmd +UStrLen(cmd), arg);
  407. err.MsgWrite(0,DCT_MSG_GENERIC_S,&*cmd);
  408. }
  409. void
  410. TranslateRecycler(
  411. SecurityTranslatorArgs * args, // in - translation options
  412. TSDResolveStats * Stats, // in - class to display stats
  413. WCHAR * path // in - drive name
  414. )
  415. {
  416. err.MsgWrite(0,DCT_MSG_PROCESSING_RECYCLER_S,path);
  417. WCHAR folder[LEN_Path];
  418. WCHAR const * recycler = L"RECYCLER";
  419. WCHAR strSid[200];
  420. WCHAR srcPath[LEN_Path];
  421. WCHAR tgtPath[LEN_Path];
  422. DWORD lenStrSid = DIM(strSid);
  423. _wfinddata_t fData;
  424. // long hRecycler;
  425. LONG_PTR hRecycler;
  426. PSID pSidSrc = NULL, pSidTgt = NULL;
  427. TRidNode * pNode;
  428. DWORD rc = 0;
  429. swprintf(folder,L"%s\\%s\\*",path,recycler);
  430. long mode = args->TranslationMode();
  431. // Windows 2000 checks the SD for the recycle bin when the recycle bin is opened. If the SD does not match the
  432. // default template (permissions for user, admin, and system), Windows displays a message that the recycle bin is corrupt.
  433. // This change may also be in NT 4 SP 7. To avoid causing this corrupt recycle bin message, we will always translate the
  434. // recycle bins in replace mode. We will not change if we are doing a remove.
  435. if (args->TranslationMode() != REMOVE_SECURITY)
  436. args->SetTranslationMode(REPLACE_SECURITY);
  437. // use _wfind to look for hidden files in the folder
  438. for ( hRecycler = _wfindfirst(folder,&fData) ; hRecycler != -1 && ( rc == 0 ); rc = (DWORD)_wfindnext(hRecycler,&fData) )
  439. {
  440. pSidSrc = SidFromString(fData.name);
  441. if ( pSidSrc )
  442. {
  443. err.MsgWrite(0,DCT_MSG_PROCESSING_RECYCLE_FOLDER_S,fData.name);
  444. pNode = (TRidNode*)args->Cache()->Lookup(pSidSrc);
  445. if ( pNode && pNode != (TRidNode*)-1 )
  446. {
  447. pSidTgt = args->Cache()->GetTgtSid(pNode);
  448. // get the target directory name
  449. GetTextualSid(pSidTgt,strSid,&lenStrSid);
  450. if ( args->LogVerbose() )
  451. err.DbgMsgWrite(0,L"Target sid is: %ls",strSid);
  452. if ( ! args->NoChange() && args->TranslationMode() != REMOVE_SECURITY )
  453. {
  454. // rename the directory
  455. swprintf(srcPath,L"%s\\%s\\%s",path,recycler,fData.name);
  456. swprintf(tgtPath,L"%s\\%s\\%s",path,recycler,strSid);
  457. if ( ! MoveFile(srcPath,tgtPath) )
  458. {
  459. rc = GetLastError();
  460. if ( (rc == ERROR_ALREADY_EXISTS) && (args->TranslationMode() == REPLACE_SECURITY) )
  461. {
  462. // the target recycle bin already exists
  463. // attempt to rename it with a suffix, so we can rename the new bin to the SID
  464. WCHAR tmpPath[LEN_Path];
  465. long ndx = 0;
  466. do
  467. {
  468. swprintf(tmpPath,L"%ls%ls%ld",tgtPath,GET_STRING(IDS_RenamedRecyclerSuffix),ndx);
  469. if (! MoveFile(tgtPath,tmpPath) )
  470. {
  471. rc = GetLastError();
  472. ndx++;
  473. }
  474. else
  475. {
  476. rc = 0;
  477. err.MsgWrite(0,DCT_MSG_RECYCLER_RENAMED_SS,tgtPath,tmpPath);
  478. }
  479. } while ( rc == ERROR_ALREADY_EXISTS );
  480. if ( ! rc )
  481. {
  482. // we have moved the pre-existing target recycler out of the way
  483. // now retry the rename
  484. if (! MoveFile(srcPath,tgtPath) )
  485. {
  486. err.SysMsgWrite(ErrE,rc,DCT_MSG_RECYCLER_RENAME_FAILED_SD,pNode->GetAcctName(),rc);
  487. }
  488. else
  489. {
  490. err.MsgWrite(0,DCT_MSG_RECYCLER_RENAMED_SS,srcPath,tgtPath);
  491. // run security translation on the new folder
  492. ResolveFilePath(args,Stats,tgtPath,TRUE,FALSE,TRUE);
  493. }
  494. }
  495. else
  496. {
  497. err.SysMsgWrite(ErrE,rc,DCT_MSG_RECYCLER_RENAME_FAILED_SD,pNode->GetAcctName(),rc);
  498. }
  499. }
  500. else
  501. {
  502. err.SysMsgWrite(ErrE,rc,DCT_MSG_RECYCLER_RENAME_FAILED_SD,pNode->GetAcctName(),rc);
  503. }
  504. }
  505. else
  506. {
  507. err.MsgWrite(0,DCT_MSG_RECYCLER_RENAMED_SS,srcPath,tgtPath);
  508. // run security translation on the new folder
  509. ResolveFilePath(args,Stats,tgtPath,TRUE,FALSE,TRUE);
  510. }
  511. }
  512. FreeSid(pSidTgt);
  513. }
  514. FreeSid(pSidSrc);
  515. }
  516. }
  517. // set the translation mode back to its original value
  518. args->SetTranslationMode(mode);
  519. }
  520. // if the specified node is a normal share, this attempts to convert it to a path
  521. // using the administrative shares
  522. void
  523. BuildAdminPathForShare(
  524. TPathNode * tnode,
  525. WCHAR * adminShare
  526. )
  527. {
  528. // if all else fails, return the same name as specified in the node
  529. UStrCpy(adminShare,tnode->GetPathName());
  530. SHARE_INFO_502 * shInfo = NULL;
  531. DWORD rc = 0;
  532. WCHAR shareName[LEN_Path];
  533. WCHAR * slash = NULL;
  534. UStrCpy(shareName,tnode->GetPathName() + UStrLen(tnode->GetServerName()) +1);
  535. slash = wcschr(shareName,L'\\');
  536. if ( slash )
  537. *slash = 0;
  538. rc = NetShareGetInfo(tnode->GetServerName(),shareName,502,(LPBYTE*)&shInfo);
  539. if ( ! rc )
  540. {
  541. if ( *shInfo->shi502_path )
  542. {
  543. // build the administrative path name for the share
  544. UStrCpy(adminShare,tnode->GetServerName());
  545. UStrCpy(adminShare + UStrLen(adminShare),L"\\");
  546. UStrCpy(adminShare + UStrLen(adminShare),shInfo->shi502_path);
  547. WCHAR * colon = wcschr(adminShare,L':');
  548. if ( colon )
  549. {
  550. *colon = L'$';
  551. UStrCpy(adminShare + UStrLen(adminShare),L"\\");
  552. UStrCpy(adminShare + UStrLen(adminShare),slash+1);
  553. }
  554. else
  555. {
  556. // something went wrong -- revert to the given path
  557. UStrCpy(adminShare,tnode->GetPathName());
  558. }
  559. }
  560. NetApiBufferFree(shInfo);
  561. }
  562. }
  563. // Main routine for resolving file and directory SD's.
  564. int
  565. ResolveAll(
  566. SecurityTranslatorArgs * args, // in- translation settings
  567. TSDResolveStats * Stats // in- counts of examined, changed objects, etc.
  568. )
  569. {
  570. WCHAR * warg;
  571. WCHAR * machine;
  572. UINT errmode;
  573. int retcode = 0;
  574. TPathNode * tnode;
  575. errmode = SetErrorMode(SEM_FAILCRITICALERRORS);
  576. if ( ! retcode )
  577. {
  578. WriteOptions(args);
  579. Stats->InitDisplay(args->NoChange());
  580. err.MsgWrite(0,DCT_MSG_FST_STARTING);
  581. // Process Files and Directories
  582. if (! args->IsLocalSystem() )
  583. {
  584. TNodeListEnum tenum;
  585. for (tnode = (TPathNode *)tenum.OpenFirst((TNodeList *)args->PathList()) ; tnode ; tnode = (TPathNode *)tenum.Next() )
  586. {
  587. DWORD rc;
  588. BOOL needToGetBR = FALSE;
  589. // BOOL abort = FALSE;
  590. // BOOL firstTime = TRUE;
  591. warg = tnode->GetPathName();
  592. machine = GetMachineName(warg);
  593. needToGetBR = ( args->TranslateFiles() );
  594. if ( *tnode->GetServerName() && ! args->IsLocalSystem() )
  595. {
  596. warg = tnode->GetPathName();
  597. err.MsgWrite(0,DCT_MSG_PROCESSING_S,warg);
  598. if ( args->TranslateFiles() )
  599. {
  600. if ( needToGetBR )
  601. {
  602. GetBkupRstrPriv(tnode->GetServerName());
  603. }
  604. if ( IsMachineName(warg) )
  605. {
  606. // need to process each drive on this machine
  607. TVolumeEnum vEnum;
  608. rc = vEnum.Open(warg,VERIFY_PERSISTENT_ACLS,args->LogVerbose());
  609. if ( rc )
  610. {
  611. err.SysMsgWrite(ErrE,rc,DCT_MSG_ERROR_ACCESSING_DRIVES_SD,warg,rc);
  612. }
  613. else
  614. {
  615. while ( warg = vEnum.Next() )
  616. {
  617. ResolveFilePath(args,
  618. Stats,
  619. warg,
  620. false, // not valid alone
  621. false, // no wildcard
  622. true ); // container
  623. }
  624. warg = machine;
  625. }
  626. vEnum.Close();
  627. }
  628. else
  629. {
  630. WCHAR adminShare[LEN_Path];
  631. // Verify that the volume is NTFS
  632. rc = tnode->VerifyPersistentAcls();
  633. switch ( rc )
  634. {
  635. case ERROR_SUCCESS:
  636. // Process the path
  637. // if it's a share name, process the root of the share
  638. if( IsShareName(tnode->GetPathName()) )
  639. {
  640. WCHAR sharePath[LEN_Path];
  641. swprintf(sharePath,L"%s\\.",tnode->GetPathName());
  642. TFileSD sd(sharePath);
  643. if ( sd.HasSecurity() )
  644. {
  645. sd.ResolveSD(args,
  646. Stats,
  647. directory,
  648. NULL);
  649. }
  650. }
  651. // if this is a normal share, convert it to an administrative share
  652. // path, so that we can take advantage of backup/restore privileges
  653. BuildAdminPathForShare(tnode,adminShare);
  654. ResolveFilePath(args,
  655. Stats,
  656. adminShare,
  657. !IsShareName(tnode->GetPathName()),
  658. ContainsWildcard(tnode->GetPathName()),
  659. tnode->IsContainer() || IsShareName(tnode->GetPathName()));
  660. break;
  661. case ERROR_NO_SECURITY_ON_OBJECT:
  662. err.MsgWrite(ErrW,DCT_MSG_SKIPPING_FAT_VOLUME_S,warg);
  663. break;
  664. default:
  665. err.SysMsgWrite(ErrE,rc,DCT_MSG_SKIPPING_PATH_SD,warg,rc );
  666. break;
  667. }
  668. }
  669. }
  670. // Process the shares for this machine
  671. if ( args->TranslateShares() )
  672. {
  673. if ( IsMachineName(warg) )
  674. {
  675. err.MsgWrite(0,DCT_MSG_PROCESSING_SHARES_S,tnode->GetServerName());
  676. ServerResolveShares(tnode->GetServerName(),args,Stats);
  677. }
  678. else if ( IsShareName(warg) )
  679. {
  680. TShareSD sd(warg);
  681. if ( sd.HasSecurity() )
  682. {
  683. if ( args->LogVerbose() )
  684. {
  685. err.MsgWrite(0,DCT_MSG_PROCESSING_SHARE_S,warg);
  686. }
  687. sd.ResolveSD(args,
  688. Stats,
  689. share,
  690. NULL);
  691. }
  692. }
  693. }
  694. }
  695. else
  696. {
  697. // this is a local path
  698. // Verify that the volume is NTFS
  699. DWORD rc2;
  700. GetBkupRstrPriv((WCHAR*)NULL);
  701. rc2 = tnode->VerifyPersistentAcls();
  702. switch ( rc2 )
  703. {
  704. case ERROR_SUCCESS:
  705. // Process the path
  706. if ( args->TranslateFiles() )
  707. {
  708. ResolveFilePath(args,
  709. Stats,
  710. tnode->GetPathName(),
  711. true, // isValidAlone
  712. ContainsWildcard(tnode->GetPathName()),
  713. tnode->IsContainer() );
  714. }
  715. break;
  716. case ERROR_NO_SECURITY_ON_OBJECT:
  717. err.MsgWrite(ErrW,DCT_MSG_SKIPPING_FAT_VOLUME_S,warg);
  718. break;
  719. default:
  720. err.SysMsgWrite(ErrE,rc2,DCT_MSG_SKIPPING_PATH_SD,warg,rc2 );
  721. break;
  722. }
  723. }
  724. if ( machine )
  725. {
  726. delete machine;
  727. machine = NULL;
  728. }
  729. }
  730. tenum.Close();
  731. }
  732. else
  733. {
  734. // Translate the entire machine
  735. err.MsgWrite(0,DCT_MSG_LOCAL_TRANSLATION);
  736. if ( args->TranslateFiles() || args->TranslateRecycler() )
  737. {
  738. GetBkupRstrPriv((WCHAR const*)NULL);
  739. // need to process each drive on this machine
  740. TVolumeEnum vEnum;
  741. vEnum.SetLocalMode(TRUE);
  742. DWORD rc2 = vEnum.Open(NULL,VERIFY_PERSISTENT_ACLS,args->LogVerbose());
  743. if ( rc2 )
  744. {
  745. err.SysMsgWrite(ErrE,rc2,DCT_MSG_ERROR_ACCESSING_LOCAL_DRIVES_D,rc2);
  746. }
  747. else
  748. {
  749. while ( warg = vEnum.Next() )
  750. {
  751. err.MsgWrite(0,DCT_MSG_PROCESSING_S,warg);
  752. if ( args->TranslateFiles() )
  753. {
  754. ResolveFilePath(args,
  755. Stats,
  756. warg,
  757. false, // not valid alone
  758. false, // no wildcard
  759. true ); // container
  760. }
  761. if ( args->TranslateRecycler() )
  762. {
  763. TranslateRecycler(args,Stats,warg);
  764. }
  765. }
  766. warg = NULL;
  767. }
  768. vEnum.Close();
  769. }
  770. if ( args->TranslateShares() )
  771. {
  772. err.MsgWrite(0,DCT_MSG_PROCESSING_LOCAL_SHARES,NULL);
  773. ServerResolveShares(NULL,args,Stats);
  774. }
  775. if ( args->TranslatePrinters() )
  776. {
  777. err.MsgWrite(0,DCT_MSG_PROCESSING_LOCAL_PRINTERS,NULL);
  778. ServerResolvePrinters(NULL,args,Stats);
  779. }
  780. }
  781. Stats->DisplayPath(L"");
  782. } // end if ( ! retcode)
  783. SetErrorMode(errmode);
  784. return retcode;
  785. }