Leaked source code of windows server 2003
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.

4081 lines
121 KiB

  1. #define UNICODE
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <windows.h>
  5. #include <winioctl.h>
  6. #include <shdcom.h>
  7. #include <shellapi.h>
  8. #include <smbdebug.h>
  9. #include <time.h>
  10. #include "struct.h"
  11. #include "messages.h"
  12. #include "cscapi.h"
  13. CHAR *ProgName = "cscutil";
  14. #define CSC_MERGE_KEEP_LOCAL 1
  15. #define CSC_MERGE_KEEP_NETWORK 2
  16. #define CSC_MERGE_KEEP_BOTH 3
  17. //
  18. // Arguments (ie '/arg:')
  19. //
  20. MAKEARG(Pin);
  21. MAKEARG(UnPin);
  22. MAKEARG(Delete);
  23. MAKEARG(DeleteShadow);
  24. MAKEARG(GetShadow);
  25. MAKEARG(GetShadowInfo);
  26. MAKEARG(ShareId);
  27. MAKEARG(Fill);
  28. MAKEARG(Db);
  29. MAKEARG(SetShareStatus);
  30. MAKEARG(Purge);
  31. MAKEARG(IsServerOffline);
  32. MAKEARG(EnumForStats);
  33. MAKEARG(SetSpace);
  34. MAKEARG(Merge);
  35. MAKEARG(QueryFile);
  36. MAKEARG(QueryFileEx);
  37. MAKEARG(QueryShare);
  38. MAKEARG(Check);
  39. MAKEARG(ExclusionList);
  40. MAKEARG(BWConservationList);
  41. MAKEARG(Disconnect);
  42. MAKEARG(Reconnect);
  43. MAKEARG(Enum);
  44. MAKEARG(Move);
  45. MAKEARG(Bitcopy);
  46. MAKEARG(RandW);
  47. MAKEARG(Offset);
  48. MAKEARG(MoveShare);
  49. //
  50. // Switches (ie '/arg')
  51. //
  52. SWITCH(Info);
  53. SWITCH(Fcblist);
  54. SWITCH(DBStatus);
  55. SWITCH(PQEnum);
  56. SWITCH(User);
  57. SWITCH(System);
  58. SWITCH(Inherit);
  59. SWITCH(Recurse);
  60. SWITCH(Abort);
  61. SWITCH(Skip);
  62. SWITCH(Ask);
  63. SWITCH(Eof);
  64. SWITCH(Retry);
  65. SWITCH(Touch);
  66. SWITCH(Enable);
  67. SWITCH(Disable);
  68. SWITCH(Ioctl);
  69. SWITCH(Flags);
  70. SWITCH(GetSpace);
  71. SWITCH(Encrypt);
  72. SWITCH(Decrypt);
  73. SWITCH(Db);
  74. SWITCH(Set);
  75. SWITCH(Clear);
  76. SWITCH(Purge);
  77. SWITCH(Detector);
  78. SWITCH(Switches);
  79. SWITCH(Debug);
  80. SWITCH(Help);
  81. SWITCH(HelpHelp);
  82. SWITCH(Enum);
  83. SWITCH(Resid);
  84. SWITCH(Full);
  85. //
  86. // The macro can not make these
  87. //
  88. WCHAR SwQ[] = L"/?";
  89. BOOLEAN fSwQ;
  90. WCHAR SwQQ[] = L"/??";
  91. BOOLEAN fSwQQ;
  92. //
  93. // Globals
  94. //
  95. LPWSTR pwszDisconnectArg = NULL;
  96. LPWSTR pwszExclusionListArg = NULL;
  97. LPWSTR pwszBWConservationListArg = NULL;
  98. LPWSTR pwszSetShareStatusArg = NULL;
  99. LPWSTR pwszIsServerOfflineArg = NULL;
  100. LPWSTR pwszPurgeArg = NULL;
  101. LPWSTR pwszPinUnPinArg = NULL;
  102. LPWSTR pwszDeleteArg = NULL;
  103. LPWSTR pwszDeleteShadowArg = NULL;
  104. LPWSTR pwszGetShadowArg = NULL;
  105. LPWSTR pwszGetShadowInfoArg = NULL;
  106. LPWSTR pwszShareIdArg = NULL;
  107. LPWSTR pwszReconnectArg = NULL;
  108. LPWSTR pwszQueryFileArg = NULL;
  109. LPWSTR pwszQueryFileExArg = NULL;
  110. LPWSTR pwszDbArg = NULL;
  111. LPWSTR pwszSetSpaceArg = NULL;
  112. LPWSTR pwszQueryShareArg = NULL;
  113. LPWSTR pwszMoveArg = NULL;
  114. LPWSTR pwszMergeArg = NULL;
  115. LPWSTR pwszFillArg = NULL;
  116. LPWSTR pwszEnumArg = NULL;
  117. LPWSTR pwszRandWArg = NULL;
  118. LPWSTR pwszBitcopyArg = NULL;
  119. LPWSTR pwszOffsetArg = NULL;
  120. LPWSTR pwszEnumForStatsArg = NULL;
  121. LPWSTR pwszCheckArg = NULL;
  122. char statusName[4][32] = {
  123. "Local Path",
  124. "Offline Share",
  125. "Online Share",
  126. "No CSC"
  127. };
  128. DWORD
  129. Usage(
  130. BOOLEAN fHelpHelp);
  131. BOOLEAN
  132. CmdProcessArg(
  133. LPWSTR Arg);
  134. DWORD
  135. CmdInfo(
  136. ULONG Cmd);
  137. DWORD
  138. CmdDBStatus(
  139. VOID);
  140. DWORD
  141. CmdPurge(
  142. PWSTR PurgeArg);
  143. DWORD
  144. CmdDetector(
  145. VOID);
  146. DWORD
  147. CmdPQEnum(
  148. VOID);
  149. DWORD
  150. CmdGetSpace(
  151. VOID);
  152. DWORD
  153. CmdSwitches(
  154. VOID);
  155. DWORD
  156. CmdDisconnect(
  157. PWSTR DisconnectArg);
  158. DWORD
  159. CmdExclusionList(
  160. PWSTR ExclusionListArg);
  161. DWORD
  162. CmdBWConservationList(
  163. PWSTR BWConservationListArg);
  164. DWORD
  165. CmdSetShareStatus(
  166. PWSTR SetShareStatusArg);
  167. DWORD
  168. CmdIsServerOffline(
  169. PWSTR IsServerOfflineArg);
  170. DWORD
  171. CmdReconnect(
  172. PWSTR ReconnectArg);
  173. DWORD
  174. CmdQueryFile(
  175. PWSTR QueryFileArg);
  176. DWORD
  177. CmdQueryFileEx(
  178. PWSTR QueryFileExArg);
  179. DWORD
  180. CmdDb(
  181. PWSTR DbArg);
  182. DWORD
  183. CmdSetSpace(
  184. PWSTR SetSpaceArg);
  185. DWORD
  186. CmdQueryShare(
  187. PWSTR QueryShareArg);
  188. DWORD
  189. CmdMove(
  190. PWSTR MoveArg);
  191. DWORD
  192. CmdMerge(
  193. PWSTR MergeArg);
  194. DWORD
  195. CmdEncryptDecrypt(
  196. BOOL fEncrypt);
  197. DWORD
  198. CmdFill(
  199. PWSTR FillArg);
  200. DWORD
  201. CmdCheck(
  202. PWSTR CheckArg);
  203. DWORD
  204. CmdEnum(
  205. PWSTR CmdEnumArg);
  206. DWORD
  207. CmdRandW(
  208. PWSTR CmdRandWArg);
  209. DWORD
  210. CmdBitcopy(
  211. PWSTR CmdBitcopyArg);
  212. DWORD
  213. CmdEnumForStats(
  214. PWSTR EnumForStatsArg);
  215. DWORD
  216. CmdDelete(
  217. PWSTR DeleteArg);
  218. DWORD
  219. CmdGetShadow(
  220. PWSTR GetShadowArg);
  221. DWORD
  222. CmdGetShadowInfo(
  223. PWSTR GetShadowInfoArg);
  224. DWORD
  225. CmdShareId(
  226. PWSTR ShareIdArg);
  227. DWORD
  228. CmdDeleteShadow(
  229. PWSTR DeleteArg);
  230. DWORD
  231. CmdPinUnPin(
  232. BOOL fPin,
  233. PWSTR PinArg);
  234. DWORD
  235. CmdMoveShare(
  236. PWSTR source,
  237. PWSTR dest);
  238. SHARESTATUS
  239. GetCSCStatus (
  240. const WCHAR * pwszPath);
  241. BOOL
  242. GetShareStatus (
  243. const WCHAR * pwszShare,
  244. DWORD * pdwStatus,
  245. DWORD * pdwPinCount,
  246. DWORD * pdwHints);
  247. void
  248. MoveDirInCSC (
  249. const WCHAR * pwszSource,
  250. const WCHAR * pwszDest,
  251. const WCHAR * pwszSkipSubdir,
  252. SHARESTATUS StatusFrom, SHARESTATUS StatusTo,
  253. BOOL bAllowRdrTimeoutForDel,
  254. BOOL bAllowRdrTimeoutForRen);
  255. DWORD
  256. DoCSCRename (
  257. const WCHAR * pwszSource,
  258. const WCHAR * pwszDest,
  259. BOOL bOverwrite,
  260. BOOL bAllowRdrTimeout);
  261. DWORD
  262. DeleteCSCFileTree (
  263. const WCHAR * pwszSource,
  264. const WCHAR * pwszSkipSubdir,
  265. BOOL bAllowRdrTimeout);
  266. DWORD
  267. DeleteCSCFile (
  268. const WCHAR * pwszPath,
  269. BOOL bAllowRdrTimeout);
  270. DWORD
  271. DeleteCSCShareIfEmpty (
  272. LPCTSTR pwszFileName,
  273. SHARESTATUS shStatus);
  274. DWORD
  275. MergePinInfo (
  276. LPCTSTR pwszSource,
  277. LPCTSTR pwszDest,
  278. SHARESTATUS StatusFrom,
  279. SHARESTATUS StatusTo);
  280. DWORD
  281. PinIfNecessary (
  282. const WCHAR * pwszPath,
  283. SHARESTATUS shStatus);
  284. DWORD
  285. CscMergeFillAsk(
  286. LPCWSTR lpszFullPath);
  287. DWORD
  288. MyCscMergeProcW(
  289. LPCWSTR lpszFullPath,
  290. DWORD dwStatus,
  291. DWORD dwHintFlags,
  292. DWORD dwPinCount,
  293. WIN32_FIND_DATAW *lpFind32,
  294. DWORD dwReason,
  295. DWORD dwParam1,
  296. DWORD dwParam2,
  297. DWORD_PTR dwContext);
  298. DWORD
  299. MyCscFillProcW(
  300. LPCWSTR lpszFullPath,
  301. DWORD dwStatus,
  302. DWORD dwHintFlags,
  303. DWORD dwPinCount,
  304. WIN32_FIND_DATAW *lpFind32,
  305. DWORD dwReason,
  306. DWORD dwParam1,
  307. DWORD dwParam2,
  308. DWORD_PTR dwContext);
  309. DWORD
  310. MyEncryptDecryptProcW(
  311. LPCWSTR lpszFullPath,
  312. DWORD dwStatus,
  313. DWORD dwHintFlags,
  314. DWORD dwPinCount,
  315. WIN32_FIND_DATAW *lpFind32,
  316. DWORD dwReason,
  317. DWORD dwParam1,
  318. DWORD dwParam2,
  319. DWORD_PTR dwContext);
  320. DWORD
  321. MyEnumForStatsProcW(
  322. LPCWSTR lpszFullPath,
  323. DWORD dwStatus,
  324. DWORD dwHintFlags,
  325. DWORD dwPinCount,
  326. WIN32_FIND_DATAW *lpFind32,
  327. DWORD dwReason,
  328. DWORD dwParam1,
  329. DWORD dwParam2,
  330. DWORD_PTR dwContext);
  331. DWORD
  332. FileStatusToEnglish(
  333. DWORD Status,
  334. LPWSTR OutputBuffer);
  335. DWORD
  336. HintsToEnglish(
  337. DWORD Hint,
  338. LPWSTR OutputBuffer);
  339. DWORD
  340. ShareStatusToEnglish(
  341. DWORD Status,
  342. LPWSTR OutputBuffer);
  343. BOOLEAN
  344. LooksToBeAShare(LPWSTR Name);
  345. LONG
  346. CountOffsetArgs(
  347. PWSTR OffsetArg,
  348. ULONG OffsetArray[]);
  349. DWORD
  350. DumpBitMap(
  351. LPWSTR lpszTempName);
  352. VOID
  353. ErrorMessage(
  354. IN HRESULT hr,
  355. ...);
  356. WCHAR NameBuf[MAX_PATH + 25];
  357. WCHAR vtzDefaultExclusionList[] = L" *.SLM *.MDB *.LDB *.MDW *.MDE *.PST *.DB?"; // from ui.c
  358. //
  359. // These functions were added for Windows XP, and so we do a loadlibrary on them, so that
  360. // this utility will work on both Windows 2000 and Windows XP
  361. //
  362. typedef BOOL (*CSCQUERYFILESTATUSEXW)(LPCWSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
  363. typedef BOOL (*CSCQUERYSHARESTATUSW)(LPCWSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
  364. typedef BOOL (*CSCPURGEUNPINNEDFILES)(ULONG, PULONG, PULONG);
  365. typedef BOOL (*CSCENCRYPTDECRYPTDATABASE)(BOOL, LPCSCPROCW, DWORD_PTR);
  366. typedef BOOL (*CSCSHAREIDTOSHARENAME)(ULONG, PBYTE, PULONG);
  367. _cdecl
  368. main(int argc, char *argv[])
  369. {
  370. DWORD dwErr = ERROR_SUCCESS;
  371. LPWSTR CommandLine;
  372. LPWSTR *argvw;
  373. int argx;
  374. int argcw;
  375. // fSwDebug = TRUE;
  376. if (!CSCIsCSCEnabled()) {
  377. Usage(FALSE);
  378. ErrorMessage(MSG_CSC_DISABLED);
  379. return 1;
  380. }
  381. //
  382. // Get the command line in Unicode
  383. //
  384. CommandLine = GetCommandLine();
  385. argvw = CommandLineToArgvW(CommandLine, &argcw);
  386. if ( argvw == NULL ) {
  387. MyPrintf(L"cscutil:Can't convert command line to Unicode: %d\r\n", GetLastError() );
  388. return 1;
  389. }
  390. //
  391. // Get the arguments
  392. //
  393. if (argcw <= 1) {
  394. Usage(FALSE);
  395. dwErr = ERROR_SUCCESS;
  396. goto Cleanup;
  397. }
  398. //
  399. // Process arguments
  400. //
  401. for (argx = 1; argx < argcw; argx++) {
  402. if (CmdProcessArg(argvw[argx]) != TRUE) {
  403. dwErr = ERROR_INVALID_PARAMETER;
  404. goto Cleanup;
  405. }
  406. if (fArgMoveShare) {
  407. break;
  408. }
  409. }
  410. if (fSwDebug == TRUE) {
  411. MyPrintf(L"Do special debug stuff here\r\n");
  412. }
  413. //
  414. // Do the work
  415. //
  416. if (fSwHelp == TRUE || fSwQ == TRUE) {
  417. dwErr = Usage(FALSE);
  418. } else if (fSwHelpHelp == TRUE || fSwQQ == TRUE) {
  419. dwErr = Usage(TRUE);
  420. } else if (fSwInfo == TRUE) {
  421. dwErr = CmdInfo(DEBUG_INFO_SERVERLIST);
  422. } else if (fSwFcblist == TRUE) {
  423. dwErr = CmdInfo(DEBUG_INFO_CSCFCBSLIST);
  424. } else if (fSwGetSpace == TRUE) {
  425. dwErr = CmdGetSpace();
  426. } else if (fSwDBStatus == TRUE) {
  427. dwErr = CmdDBStatus();
  428. } else if (fArgPurge == TRUE) {
  429. dwErr = CmdPurge(pwszPurgeArg);
  430. } else if (fSwPurge == TRUE) {
  431. dwErr = CmdPurge(NULL);
  432. } else if (fSwDetector == TRUE) {
  433. dwErr = CmdDetector();
  434. } else if (fSwPQEnum == TRUE) {
  435. dwErr = CmdPQEnum();
  436. } else if (fSwFlags == TRUE) {
  437. ErrorMessage(MSG_FLAGS);
  438. dwErr = ERROR_SUCCESS;
  439. } else if (fSwEnable == TRUE) {
  440. dwErr = (CSCDoEnableDisable(TRUE) == TRUE) ? ERROR_SUCCESS : GetLastError();
  441. } else if (fSwDisable == TRUE) {
  442. dwErr = (CSCDoEnableDisable(FALSE) == TRUE) ? ERROR_SUCCESS : GetLastError();
  443. } else if (fSwSwitches == TRUE) {
  444. dwErr = CmdSwitches();
  445. } else if (fArgDisconnect == TRUE) {
  446. dwErr = CmdDisconnect(pwszDisconnectArg);
  447. } else if (fArgExclusionList == TRUE) {
  448. dwErr = CmdExclusionList(pwszExclusionListArg);
  449. } else if (fArgBWConservationList == TRUE) {
  450. dwErr = CmdBWConservationList(pwszBWConservationListArg);
  451. } else if (fArgSetShareStatus == TRUE) {
  452. dwErr = CmdSetShareStatus(pwszSetShareStatusArg);
  453. } else if (fArgIsServerOffline == TRUE) {
  454. dwErr = CmdIsServerOffline(pwszIsServerOfflineArg);
  455. } else if (fArgReconnect == TRUE) {
  456. dwErr = CmdReconnect(pwszReconnectArg);
  457. } else if (fArgQueryFile == TRUE) {
  458. dwErr = CmdQueryFile(pwszQueryFileArg);
  459. } else if (fArgQueryFileEx == TRUE) {
  460. dwErr = CmdQueryFileEx(pwszQueryFileExArg);
  461. #if defined(CSCUTIL_INTERNAL)
  462. } else if (fArgDb == TRUE) {
  463. dwErr = CmdDb(pwszDbArg);
  464. } else if (fSwDb == TRUE) {
  465. dwErr = CmdDb(NULL);
  466. } else if (fArgBitcopy == TRUE) {
  467. dwErr = CmdBitcopy(pwszBitcopyArg);
  468. #endif // CSCUTIL_INTERNAL
  469. } else if (fArgSetSpace == TRUE) {
  470. dwErr = CmdSetSpace(pwszSetSpaceArg);
  471. } else if (fArgQueryShare == TRUE) {
  472. dwErr = CmdQueryShare(pwszQueryShareArg);
  473. } else if (fArgMerge == TRUE) {
  474. dwErr = CmdMerge(pwszMergeArg);
  475. } else if (fArgMove == TRUE) {
  476. dwErr = CmdMove(pwszMoveArg);
  477. } else if (fSwEncrypt == TRUE) {
  478. dwErr = CmdEncryptDecrypt(TRUE);
  479. } else if (fSwDecrypt == TRUE) {
  480. dwErr = CmdEncryptDecrypt(FALSE);
  481. } else if (fArgFill == TRUE) {
  482. dwErr = CmdFill(pwszFillArg);
  483. } else if (fArgCheck == TRUE) {
  484. dwErr = CmdCheck(pwszCheckArg);
  485. } else if (fArgEnum == TRUE) {
  486. dwErr = CmdEnum(pwszEnumArg);
  487. } else if (fSwEnum == TRUE) {
  488. dwErr = CmdEnum(NULL);
  489. } else if (fArgRandW == TRUE) {
  490. dwErr = CmdRandW(pwszRandWArg);
  491. } else if (fArgEnumForStats == TRUE) {
  492. dwErr = CmdEnumForStats(pwszEnumForStatsArg);
  493. } else if (fArgGetShadow == TRUE) {
  494. dwErr = CmdGetShadow(pwszGetShadowArg);
  495. } else if (fArgGetShadowInfo == TRUE) {
  496. dwErr = CmdGetShadowInfo(pwszGetShadowInfoArg);
  497. } else if (fArgShareId == TRUE) {
  498. dwErr = CmdShareId(pwszShareIdArg);
  499. } else if (fArgDelete == TRUE) {
  500. dwErr = CmdDelete(pwszDeleteArg);
  501. } else if (fArgDeleteShadow == TRUE) {
  502. dwErr = CmdDeleteShadow(pwszDeleteShadowArg);
  503. } else if (fArgPin == TRUE || fArgUnPin == TRUE) {
  504. dwErr = CmdPinUnPin(fArgPin, pwszPinUnPinArg);
  505. } else if (fArgMoveShare == TRUE) {
  506. if (argcw == 4) {
  507. dwErr = CmdMoveShare(argvw[2], argvw[3]);
  508. }
  509. else {
  510. dwErr = Usage(FALSE);
  511. dwErr = ERROR_INVALID_PARAMETER;
  512. }
  513. } else {
  514. dwErr = Usage(FALSE);
  515. }
  516. Cleanup:
  517. if (dwErr == ERROR_SUCCESS) {
  518. ErrorMessage(MSG_SUCCESSFUL);
  519. } else {
  520. LPWSTR MessageBuffer;
  521. DWORD dwBufferLength;
  522. dwBufferLength = FormatMessage(
  523. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  524. NULL,
  525. dwErr,
  526. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  527. (LPWSTR) &MessageBuffer,
  528. 0,
  529. NULL);
  530. ErrorMessage(MSG_ERROR, dwErr);
  531. if (dwBufferLength > 0) {
  532. MyPrintf(L"%ws\r\n", MessageBuffer);
  533. LocalFree(MessageBuffer);
  534. }
  535. }
  536. return dwErr;
  537. }
  538. BOOLEAN
  539. CmdProcessArg(LPWSTR Arg)
  540. {
  541. LONG ArgLen;
  542. BOOLEAN dwErr = FALSE;
  543. BOOLEAN FoundAnArg = FALSE;
  544. if (fSwDebug == TRUE)
  545. MyPrintf(L"ProcessArg(%ws)\r\n", Arg);
  546. if ( Arg != NULL && wcslen(Arg) > 1) {
  547. dwErr = TRUE;
  548. ArgLen = wcslen(Arg);
  549. //
  550. // Commands with args
  551. //
  552. if (_wcsnicmp(Arg, ArgDisconnect, ArgLenDisconnect) == 0) {
  553. FoundAnArg = fArgDisconnect = TRUE;
  554. if (ArgLen > ArgLenDisconnect)
  555. pwszDisconnectArg = &Arg[ArgLenDisconnect];
  556. } else if (_wcsnicmp(Arg, ArgEnum, ArgLenEnum) == 0) {
  557. FoundAnArg = fArgEnum = TRUE;
  558. if (ArgLen > ArgLenEnum)
  559. pwszEnumArg = &Arg[ArgLenEnum];
  560. } else if (_wcsnicmp(Arg, ArgMoveShare, ArgLenMoveShare) == 0) {
  561. FoundAnArg = fArgMoveShare = TRUE;
  562. #if defined(CSCUTIL_INTERNAL)
  563. } else if (_wcsnicmp(Arg, ArgReconnect, ArgLenReconnect) == 0) {
  564. FoundAnArg = fArgReconnect = TRUE;
  565. if (ArgLen > ArgLenReconnect)
  566. pwszReconnectArg = &Arg[ArgLenReconnect];
  567. } else if (_wcsnicmp(Arg, ArgPin, ArgLenPin) == 0) {
  568. FoundAnArg = fArgPin = TRUE;
  569. if (ArgLen > ArgLenPin)
  570. pwszPinUnPinArg = &Arg[ArgLenPin];
  571. } else if (_wcsnicmp(Arg, ArgUnPin, ArgLenUnPin) == 0) {
  572. FoundAnArg = fArgUnPin = TRUE;
  573. if (ArgLen > ArgLenUnPin)
  574. pwszPinUnPinArg = &Arg[ArgLenUnPin];
  575. } else if (_wcsnicmp(Arg, ArgDelete, ArgLenDelete) == 0) {
  576. FoundAnArg = fArgDelete = TRUE;
  577. if (ArgLen > ArgLenDelete)
  578. pwszDeleteArg = &Arg[ArgLenDelete];
  579. } else if (_wcsnicmp(Arg, ArgExclusionList, ArgLenExclusionList) == 0) {
  580. FoundAnArg = fArgExclusionList = TRUE;
  581. if (ArgLen > ArgLenExclusionList)
  582. pwszExclusionListArg = &Arg[ArgLenExclusionList];
  583. } else if (_wcsnicmp(Arg, ArgBWConservationList, ArgLenBWConservationList) == 0) {
  584. FoundAnArg = fArgBWConservationList = TRUE;
  585. if (ArgLen > ArgLenBWConservationList)
  586. pwszBWConservationListArg = &Arg[ArgLenBWConservationList];
  587. } else if (_wcsnicmp(Arg, ArgSetShareStatus, ArgLenSetShareStatus) == 0) {
  588. FoundAnArg = fArgSetShareStatus = TRUE;
  589. if (ArgLen > ArgLenSetShareStatus)
  590. pwszSetShareStatusArg = &Arg[ArgLenSetShareStatus];
  591. } else if (_wcsnicmp(Arg, ArgIsServerOffline, ArgLenIsServerOffline) == 0) {
  592. FoundAnArg = fArgIsServerOffline = TRUE;
  593. if (ArgLen > ArgLenIsServerOffline)
  594. pwszIsServerOfflineArg = &Arg[ArgLenIsServerOffline];
  595. } else if (_wcsnicmp(Arg, ArgPurge, ArgLenPurge) == 0) {
  596. FoundAnArg = fArgPurge = TRUE;
  597. if (ArgLen > ArgLenPurge)
  598. pwszPurgeArg = &Arg[ArgLenPurge];
  599. } else if (_wcsnicmp(Arg, ArgRandW, ArgLenRandW) == 0) {
  600. FoundAnArg = fArgRandW = TRUE;
  601. if (ArgLen > ArgLenRandW)
  602. pwszRandWArg = &Arg[ArgLenRandW];
  603. } else if (_wcsnicmp(Arg, ArgBitcopy, ArgLenBitcopy) == 0) {
  604. FoundAnArg = fArgBitcopy = TRUE;
  605. if (ArgLen > ArgLenBitcopy)
  606. pwszBitcopyArg = &Arg[ArgLenBitcopy];
  607. } else if (_wcsnicmp(Arg, ArgOffset, ArgLenOffset) == 0) {
  608. FoundAnArg = fArgOffset = TRUE;
  609. if (ArgLen > ArgLenOffset)
  610. pwszOffsetArg = &Arg[ArgLenOffset];
  611. } else if (_wcsnicmp(Arg, ArgDeleteShadow, ArgLenDeleteShadow) == 0) {
  612. FoundAnArg = fArgDeleteShadow = TRUE;
  613. if (ArgLen > ArgLenDeleteShadow)
  614. pwszDeleteShadowArg = &Arg[ArgLenDeleteShadow];
  615. } else if (_wcsnicmp(Arg, ArgQueryFile, ArgLenQueryFile) == 0) {
  616. FoundAnArg = fArgQueryFile = TRUE;
  617. if (ArgLen > ArgLenQueryFile)
  618. pwszQueryFileArg = &Arg[ArgLenQueryFile];
  619. } else if (_wcsnicmp(Arg, ArgQueryFileEx, ArgLenQueryFileEx) == 0) {
  620. FoundAnArg = fArgQueryFileEx = TRUE;
  621. if (ArgLen > ArgLenQueryFileEx)
  622. pwszQueryFileExArg = &Arg[ArgLenQueryFileEx];
  623. } else if (_wcsnicmp(Arg, ArgDb, ArgLenDb) == 0) {
  624. FoundAnArg = fArgDb = TRUE;
  625. if (ArgLen > ArgLenDb)
  626. pwszDbArg = &Arg[ArgLenDb];
  627. } else if (_wcsnicmp(Arg, ArgSetSpace, ArgLenSetSpace) == 0) {
  628. FoundAnArg = fArgSetSpace = TRUE;
  629. if (ArgLen > ArgLenSetSpace)
  630. pwszSetSpaceArg = &Arg[ArgLenSetSpace];
  631. } else if (_wcsnicmp(Arg, ArgGetShadow, ArgLenGetShadow) == 0) {
  632. FoundAnArg = fArgGetShadow = TRUE;
  633. if (ArgLen > ArgLenGetShadow)
  634. pwszGetShadowArg = &Arg[ArgLenGetShadow];
  635. } else if (_wcsnicmp(Arg, ArgGetShadowInfo, ArgLenGetShadowInfo) == 0) {
  636. FoundAnArg = fArgGetShadowInfo = TRUE;
  637. if (ArgLen > ArgLenGetShadowInfo)
  638. pwszGetShadowInfoArg = &Arg[ArgLenGetShadowInfo];
  639. } else if (_wcsnicmp(Arg, ArgShareId, ArgLenShareId) == 0) {
  640. FoundAnArg = fArgShareId = TRUE;
  641. if (ArgLen > ArgLenShareId)
  642. pwszShareIdArg = &Arg[ArgLenShareId];
  643. } else if (_wcsnicmp(Arg, ArgQueryShare, ArgLenQueryShare) == 0) {
  644. FoundAnArg = fArgQueryShare = TRUE;
  645. if (ArgLen > ArgLenQueryShare)
  646. pwszQueryShareArg = &Arg[ArgLenQueryShare];
  647. } else if (_wcsnicmp(Arg, ArgMove, ArgLenMove) == 0) {
  648. FoundAnArg = fArgMove = TRUE;
  649. if (ArgLen > ArgLenMove)
  650. pwszMoveArg = &Arg[ArgLenMove];
  651. } else if (_wcsnicmp(Arg, ArgMerge, ArgLenMerge) == 0) {
  652. FoundAnArg = fArgMerge = TRUE;
  653. if (ArgLen > ArgLenMerge)
  654. pwszMergeArg = &Arg[ArgLenMerge];
  655. } else if (_wcsnicmp(Arg, ArgFill, ArgLenFill) == 0) {
  656. FoundAnArg = fArgFill = TRUE;
  657. if (ArgLen > ArgLenFill)
  658. pwszFillArg = &Arg[ArgLenFill];
  659. } else if (_wcsnicmp(Arg, ArgCheck, ArgLenCheck) == 0) {
  660. FoundAnArg = fArgCheck = TRUE;
  661. if (ArgLen > ArgLenCheck)
  662. pwszCheckArg = &Arg[ArgLenCheck];
  663. } else if (_wcsnicmp(Arg, ArgEnumForStats, ArgLenEnumForStats) == 0) {
  664. FoundAnArg = fArgEnumForStats = TRUE;
  665. if (ArgLen > ArgLenEnumForStats)
  666. pwszEnumForStatsArg = &Arg[ArgLenEnumForStats];
  667. #endif // CSCUTIL_INTERNAL
  668. }
  669. // Switches go at the end!!
  670. if (_wcsicmp(Arg, SwHelp) == 0) {
  671. FoundAnArg = fSwHelp = TRUE;
  672. } else if (_wcsicmp(Arg, SwResid) == 0) {
  673. FoundAnArg = fSwTouch = fSwEnum = fSwRecurse = TRUE;
  674. } else if (_wcsicmp(Arg, SwFull) == 0) {
  675. FoundAnArg = fSwFull = TRUE;
  676. } else if (_wcsicmp(Arg, SwTouch) == 0) {
  677. FoundAnArg = fSwTouch = TRUE;
  678. } else if (_wcsicmp(Arg, SwEnum) == 0) {
  679. FoundAnArg = fSwEnum = TRUE;
  680. } else if (_wcsicmp(Arg, SwQQ) == 0) {
  681. FoundAnArg = fSwQQ = TRUE;
  682. } else if (_wcsicmp(Arg, SwQ) == 0) {
  683. FoundAnArg = fSwQ = TRUE;
  684. } else if (_wcsicmp(Arg, SwRecurse) == 0) {
  685. FoundAnArg = fSwRecurse = TRUE;
  686. #if defined(CSCUTIL_INTERNAL)
  687. } else if (_wcsicmp(Arg, SwDebug) == 0) {
  688. FoundAnArg = fSwDebug = TRUE;
  689. } else if (_wcsicmp(Arg, SwHelpHelp) == 0) {
  690. FoundAnArg = fSwHelpHelp = TRUE;
  691. } else if (_wcsicmp(Arg, SwPQEnum) == 0) {
  692. FoundAnArg = fSwPQEnum = TRUE;
  693. } else if (_wcsicmp(Arg, SwInfo) == 0) {
  694. FoundAnArg = fSwInfo = TRUE;
  695. } else if (_wcsicmp(Arg, SwDBStatus) == 0) {
  696. FoundAnArg = fSwDBStatus = TRUE;
  697. } else if (_wcsicmp(Arg, SwPurge) == 0) {
  698. FoundAnArg = fSwPurge = TRUE;
  699. } else if (_wcsicmp(Arg, SwDetector) == 0) {
  700. FoundAnArg = fSwDetector = TRUE;
  701. } else if (_wcsicmp(Arg, SwGetSpace) == 0) {
  702. FoundAnArg = fSwGetSpace = TRUE;
  703. } else if (_wcsicmp(Arg, SwDb) == 0) {
  704. FoundAnArg = fSwDb = TRUE;
  705. } else if (_wcsicmp(Arg, SwFcblist) == 0) {
  706. FoundAnArg = fSwFcblist = TRUE;
  707. } else if (_wcsicmp(Arg, SwEnable) == 0) {
  708. FoundAnArg = fSwEnable = TRUE;
  709. } else if (_wcsicmp(Arg, SwDisable) == 0) {
  710. FoundAnArg = fSwDisable = TRUE;
  711. } else if (_wcsicmp(Arg, SwSwitches) == 0) {
  712. FoundAnArg = fSwSwitches = TRUE;
  713. } else if (_wcsicmp(Arg, SwUser) == 0) {
  714. FoundAnArg = fSwUser = TRUE;
  715. } else if (_wcsicmp(Arg, SwSystem) == 0) {
  716. FoundAnArg = fSwSystem = TRUE;
  717. } else if (_wcsicmp(Arg, SwInherit) == 0) {
  718. FoundAnArg = fSwInherit = TRUE;
  719. } else if (_wcsicmp(Arg, SwAbort) == 0) {
  720. FoundAnArg = fSwAbort = TRUE;
  721. } else if (_wcsicmp(Arg, SwSkip) == 0) {
  722. FoundAnArg = fSwSkip = TRUE;
  723. } else if (_wcsicmp(Arg, SwAsk) == 0) {
  724. FoundAnArg = fSwAsk = TRUE;
  725. } else if (_wcsicmp(Arg, SwEof) == 0) {
  726. FoundAnArg = fSwEof = TRUE;
  727. } else if (_wcsicmp(Arg, SwRetry) == 0) {
  728. FoundAnArg = fSwRetry = TRUE;
  729. } else if (_wcsicmp(Arg, SwSet) == 0) {
  730. FoundAnArg = fSwSet = TRUE;
  731. } else if (_wcsicmp(Arg, SwClear) == 0) {
  732. FoundAnArg = fSwClear = TRUE;
  733. } else if (_wcsicmp(Arg, SwFlags) == 0) {
  734. FoundAnArg = fSwFlags = TRUE;
  735. } else if (_wcsicmp(Arg, SwIoctl) == 0) {
  736. FoundAnArg = fSwIoctl = TRUE;
  737. } else if (_wcsicmp(Arg, SwEncrypt) == 0) {
  738. FoundAnArg = fSwEncrypt = TRUE;
  739. } else if (_wcsicmp(Arg, SwDecrypt) == 0) {
  740. FoundAnArg = fSwDecrypt = TRUE;
  741. #endif // CSCUTIL_INTERNAL
  742. }
  743. if (FoundAnArg == FALSE) {
  744. ErrorMessage(MSG_UNRECOGNIZED_OPTION, &Arg[1]);
  745. dwErr = FALSE;
  746. goto AllDone;
  747. }
  748. }
  749. AllDone:
  750. if (fSwDebug == TRUE)
  751. MyPrintf(L"ProcessArg exit %d\r\n", dwErr);
  752. return dwErr;
  753. }
  754. DWORD
  755. Usage(
  756. BOOLEAN fHelpHelp)
  757. {
  758. #if defined(CSCUTIL_INTERNAL)
  759. ErrorMessage(MSG_USAGE);
  760. if (fHelpHelp == TRUE)
  761. ErrorMessage(MSG_USAGE_EX);
  762. #else
  763. ErrorMessage(MSG_USAGE2);
  764. if (fHelpHelp == TRUE)
  765. ErrorMessage(MSG_USAGE_EX2);
  766. #endif // CSCUTIL_INTERNAL
  767. return ERROR_SUCCESS;
  768. }
  769. DWORD
  770. CmdMoveShare(
  771. PWSTR source,
  772. PWSTR dest)
  773. {
  774. SHARESTATUS sFrom, sTo;
  775. //printf( "Attempting move from %ws to %ws.\n", source, dest );
  776. sFrom = GetCSCStatus(source);
  777. //printf( "INFO: %ws status = %s\n", source, statusName[sFrom] );
  778. sTo = GetCSCStatus(dest);
  779. //printf( "INFO: %ws status = %s\n", dest, statusName[sTo] );
  780. // Check and make sure this is valid
  781. if( (sFrom == PathLocal) || (sTo == PathLocal) )
  782. {
  783. ErrorMessage(MSG_TO_LOCAL);
  784. return ERROR_INVALID_PARAMETER;
  785. }
  786. if( (sFrom == NoCSC) || (sTo == NoCSC) )
  787. {
  788. ErrorMessage(MSG_NO_CSC);
  789. return ERROR_INVALID_PARAMETER;
  790. }
  791. if( sTo == ShareOffline )
  792. {
  793. ErrorMessage(MSG_NOT_ONLINE);
  794. return ERROR_CSCSHARE_OFFLINE;
  795. }
  796. MoveDirInCSC( source, dest, NULL, ShareOnline, ShareOnline, TRUE, TRUE );
  797. return ERROR_SUCCESS;
  798. }
  799. //+--------------------------------------------------------------------------
  800. //
  801. // Function: MoveDirInCSC
  802. //
  803. // Synopsis: this function moves a directory within the CSC cache without
  804. // prejudice. If the destination is a local path, it just deletes
  805. // the source tree from the cache
  806. //
  807. // Arguments: [in] pwszSource : the source path
  808. // [in] pwszDest : the dest path
  809. // [in] pwszSkipSubdir : the directory to skip while moving
  810. // [in] StatusFrom : the CSC status of the source path
  811. // [in] StatusTo : the CSC status of the dest. path
  812. // [in] bAllowRdrTimeout : if stuff needs to be deleted from the
  813. // cache, we may not succeed immediately since
  814. // the rdr keeps the handles to recently opened
  815. // files open. This paramaters tells the function
  816. // whether it needs to wait and retry
  817. //
  818. // Returns: nothing. it just tries its best.
  819. //
  820. // History: 11/21/1998 RahulTh created
  821. //
  822. // Notes: the value of bAllowRdrTimeout is always ignored for the
  823. // in-cache rename operation. we always want to wait for
  824. // the timeout.
  825. //
  826. //---------------------------------------------------------------------------
  827. void MoveDirInCSC (const WCHAR * pwszSource, const WCHAR * pwszDest,
  828. const WCHAR * pwszSkipSubdir,
  829. SHARESTATUS StatusFrom, SHARESTATUS StatusTo,
  830. BOOL bAllowRdrTimeoutForDel,
  831. BOOL bAllowRdrTimeoutForRen)
  832. {
  833. WIN32_FIND_DATA findData;
  834. DWORD dwFileStatus;
  835. DWORD dwPinCount;
  836. HANDLE hCSCFind;
  837. DWORD dwHintFlags;
  838. FILETIME origTime;
  839. WCHAR * pwszPath;
  840. WCHAR * pwszEnd;
  841. int len;
  842. DWORD StatusCSCRen = ERROR_SUCCESS;
  843. if (PathLocal == StatusFrom)
  844. return; //there is nothing to do. nothing was cached.
  845. if (PathLocal == StatusTo)
  846. {
  847. //the destination is a local path, so we should just delete the
  848. //files from the source
  849. DeleteCSCFileTree (pwszSource, pwszSkipSubdir, bAllowRdrTimeoutForDel);
  850. }
  851. else
  852. {
  853. pwszPath = (WCHAR *) malloc (sizeof (WCHAR) * ((len = wcslen (pwszSource)) + MAX_PATH + 2));
  854. if (!pwszPath || len <= 0)
  855. return;
  856. wcscpy (pwszPath, pwszSource);
  857. pwszEnd = pwszPath + len;
  858. if (L'\\' != pwszEnd[-1])
  859. {
  860. *pwszEnd++ = L'\\';
  861. }
  862. hCSCFind = CSCFindFirstFile (pwszSource, &findData, &dwFileStatus,
  863. &dwPinCount, &dwHintFlags, &origTime);
  864. if (INVALID_HANDLE_VALUE != hCSCFind)
  865. {
  866. do
  867. {
  868. if (0 != _wcsicmp (L".", findData.cFileName) &&
  869. 0 != _wcsicmp (L"..", findData.cFileName) &&
  870. (!pwszSkipSubdir || (0 != _wcsicmp (findData.cFileName, pwszSkipSubdir))))
  871. {
  872. wcscpy (pwszEnd, findData.cFileName);
  873. if (ERROR_SUCCESS == StatusCSCRen)
  874. {
  875. StatusCSCRen = DoCSCRename (pwszPath, pwszDest, TRUE, bAllowRdrTimeoutForRen);
  876. }
  877. else
  878. {
  879. StatusCSCRen = DoCSCRename (pwszPath, pwszDest, TRUE, FALSE);
  880. }
  881. }
  882. } while ( CSCFindNextFile (hCSCFind, &findData, &dwFileStatus,
  883. &dwPinCount, &dwHintFlags, &origTime)
  884. );
  885. CSCFindClose (hCSCFind);
  886. }
  887. //merge the pin info. at the top level folder
  888. MergePinInfo (pwszSource, pwszDest, StatusFrom, StatusTo);
  889. //remove the share - Navjot.
  890. if (!CSCDeleteW(pwszSource))
  891. StatusCSCRen = GetLastError();
  892. }
  893. return;
  894. }
  895. //+--------------------------------------------------------------------------
  896. //
  897. // Function: DoCSCRename
  898. //
  899. // Synopsis: does a file rename within the CSC cache.
  900. //
  901. // Arguments: [in] pwszSource : full source path
  902. // [in] pwszDest : full path to destination directory
  903. // [in] bOverwrite : overwrite if the file/folder exists at
  904. // the destination
  905. // [in] bAllowRdrTimeout : if TRUE, retry for 10 seconds on failure
  906. // so that rdr and mem. mgr. get enough time to
  907. // release the handles.
  908. //
  909. // Returns: ERROR_SUCCESS if the rename was successful.
  910. // an error code otherwise.
  911. //
  912. // History: 5/26/1999 RahulTh created
  913. //
  914. // Notes: no validation of parameters is done. The caller is responsible
  915. // for that
  916. //
  917. //---------------------------------------------------------------------------
  918. DWORD DoCSCRename (const WCHAR * pwszSource, const WCHAR * pwszDest,
  919. BOOL bOverwrite, BOOL bAllowRdrTimeout)
  920. {
  921. DWORD Status = ERROR_SUCCESS;
  922. BOOL bStatus;
  923. int i;
  924. bStatus = CSCDoLocalRename (pwszSource, pwszDest, bOverwrite);
  925. if (!bStatus)
  926. {
  927. Status = GetLastError();
  928. if (ERROR_SUCCESS != Status &&
  929. ERROR_FILE_NOT_FOUND != Status &&
  930. ERROR_PATH_NOT_FOUND != Status &&
  931. ERROR_INVALID_PARAMETER != Status &&
  932. ERROR_BAD_NETPATH != Status)
  933. {
  934. if (bAllowRdrTimeout)
  935. {
  936. if (!bOverwrite && ERROR_FILE_EXISTS == Status)
  937. {
  938. Status = ERROR_SUCCESS;
  939. }
  940. else
  941. {
  942. for (i = 0; i < 11; i++)
  943. {
  944. Sleep (1000); //wait for the handle to be released
  945. bStatus = CSCDoLocalRename (pwszSource, pwszDest, bOverwrite);
  946. if (bStatus)
  947. {
  948. Status = ERROR_SUCCESS;
  949. break;
  950. }
  951. }
  952. }
  953. }
  954. }
  955. else
  956. {
  957. Status = ERROR_SUCCESS;
  958. }
  959. }
  960. return Status;
  961. }
  962. //+--------------------------------------------------------------------------
  963. //
  964. // Function: DeleteCSCFileTree
  965. //
  966. // Synopsis: deletes a file tree from the CSC
  967. //
  968. // Arguments: [in] pwszSource : the path to the folder whose contents should
  969. // be deleted
  970. // [in] pwszSkipSubdir : name of the subdirectory to be skipped.
  971. // [in] bAllowRdrTimeout : if true, makes multiple attempts to
  972. // delete the file since the rdr may have left
  973. // the handle open for sometime which can result
  974. // in an ACCESS_DENIED message.
  975. //
  976. // Returns: ERROR_SUCCESS if the deletion was successful. An error code
  977. // otherwise.
  978. //
  979. // History: 11/21/1998 RahulTh created
  980. //
  981. // Notes:
  982. //
  983. //---------------------------------------------------------------------------
  984. DWORD DeleteCSCFileTree (const WCHAR * pwszSource, const WCHAR * pwszSkipSubdir,
  985. BOOL bAllowRdrTimeout)
  986. {
  987. WIN32_FIND_DATA findData;
  988. DWORD dwFileStatus;
  989. DWORD dwPinCount;
  990. HANDLE hCSCFind;
  991. DWORD dwHintFlags;
  992. FILETIME origTime;
  993. WCHAR * pwszPath;
  994. WCHAR * pwszEnd;
  995. int len;
  996. DWORD Status = ERROR_SUCCESS;
  997. pwszPath = (WCHAR *) malloc (sizeof(WCHAR) * ((len = wcslen(pwszSource)) + MAX_PATH + 2));
  998. if (!pwszPath)
  999. return ERROR_OUTOFMEMORY; //nothing much we can do if we run out of memory
  1000. if (len <= 0)
  1001. return ERROR_BAD_PATHNAME;
  1002. wcscpy (pwszPath, pwszSource);
  1003. pwszEnd = pwszPath + len;
  1004. if (L'\\' != pwszEnd[-1])
  1005. {
  1006. *pwszEnd++ = L'\\';
  1007. }
  1008. hCSCFind = CSCFindFirstFile (pwszSource, &findData, &dwFileStatus,
  1009. &dwPinCount, &dwHintFlags, &origTime);
  1010. if (INVALID_HANDLE_VALUE != hCSCFind)
  1011. {
  1012. do
  1013. {
  1014. if (0 != _wcsicmp (L".", findData.cFileName) &&
  1015. 0 != _wcsicmp (L"..", findData.cFileName) &&
  1016. (!pwszSkipSubdir || (0 != _wcsicmp (pwszSkipSubdir, findData.cFileName))))
  1017. {
  1018. wcscpy (pwszEnd, findData.cFileName);
  1019. if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1020. {
  1021. if (ERROR_SUCCESS != Status)
  1022. {
  1023. //no point delaying the deletes since a delete has already
  1024. //failed.
  1025. DeleteCSCFileTree (pwszPath, NULL, FALSE);
  1026. }
  1027. else
  1028. {
  1029. Status = DeleteCSCFileTree (pwszPath, NULL, bAllowRdrTimeout);
  1030. }
  1031. }
  1032. else
  1033. {
  1034. if (ERROR_SUCCESS != Status)
  1035. {
  1036. //no point delaying the delete if we have already failed.
  1037. DeleteCSCFile (pwszPath, FALSE);
  1038. }
  1039. else
  1040. {
  1041. Status = DeleteCSCFile (pwszPath, bAllowRdrTimeout);
  1042. }
  1043. }
  1044. }
  1045. } while ( CSCFindNextFile (hCSCFind, &findData, &dwFileStatus,
  1046. &dwPinCount, &dwHintFlags, &origTime)
  1047. );
  1048. CSCFindClose (hCSCFind);
  1049. }
  1050. if (ERROR_SUCCESS != Status)
  1051. {
  1052. //no point in delaying the delete if we have already failed.
  1053. DeleteCSCFile (pwszSource, FALSE);
  1054. }
  1055. else
  1056. {
  1057. Status = DeleteCSCFile (pwszSource, bAllowRdrTimeout);
  1058. }
  1059. return Status;
  1060. }
  1061. //+--------------------------------------------------------------------------
  1062. //
  1063. // Function: DeleteCSCFile
  1064. //
  1065. // Synopsis: deletes the given path. but might make repeated attempts to
  1066. // make sure that the rdr has enough time to release any handles
  1067. // that it holds.
  1068. //
  1069. // Arguments: [in] pwszPath : the path to delete.
  1070. // [in] bAllowRdrTimeout : make multiple attempts to delete the
  1071. // file with waits in between so that the rdr has
  1072. // enough time to release any held handles.
  1073. //
  1074. // Returns: ERROR_SUCCES if the delete was successful. An error code
  1075. // otherwise.
  1076. //
  1077. // History: 5/26/1999 RahulTh created
  1078. //
  1079. // Notes:
  1080. //
  1081. //---------------------------------------------------------------------------
  1082. DWORD DeleteCSCFile (const WCHAR * pwszPath, BOOL bAllowRdrTimeout)
  1083. {
  1084. BOOL bStatus;
  1085. DWORD Status = ERROR_SUCCESS;
  1086. int i;
  1087. bStatus = CSCDelete (pwszPath);
  1088. if (!bStatus)
  1089. {
  1090. Status = GetLastError();
  1091. if (ERROR_SUCCESS != Status &&
  1092. ERROR_FILE_NOT_FOUND != Status &&
  1093. ERROR_PATH_NOT_FOUND != Status &&
  1094. ERROR_INVALID_PARAMETER != Status)
  1095. {
  1096. //this is a valid error.
  1097. //so based on the value of bAllowRdrTimeout and based
  1098. //on whether we have already failed in deleting something
  1099. //we will try repeatedly to delete the file for 10 seconds
  1100. if (bAllowRdrTimeout)
  1101. {
  1102. for (i = 0; i < 11; i++)
  1103. {
  1104. Sleep (1000); //wait for 1 second and try again
  1105. bStatus = CSCDelete (pwszPath);
  1106. if (bStatus)
  1107. {
  1108. Status = ERROR_SUCCESS;
  1109. break;
  1110. }
  1111. }
  1112. }
  1113. }
  1114. else
  1115. {
  1116. Status = ERROR_SUCCESS;
  1117. }
  1118. }
  1119. return Status;
  1120. }
  1121. //+--------------------------------------------------------------------------
  1122. //
  1123. // Function: DeleteCSCShareIfEmpty
  1124. //
  1125. // Synopsis: given a file name, this function deletes from the local cache
  1126. // the share to which the file belongs if the local cache for that
  1127. // share is empty
  1128. //
  1129. // Arguments: [in] pwszFileName : the full file name -- must be UNC
  1130. // [in] shStatus : the share status - online, offline, local etc.
  1131. //
  1132. // Returns: ERROR_SUCCESS : if successful
  1133. // a win32 error code if something goes wrong
  1134. //
  1135. // History: 4/22/1999 RahulTh created
  1136. //
  1137. // Notes: we do not have to explicitly check if the share is empty
  1138. // because if it is not, then the delete will fail anyway
  1139. //
  1140. //---------------------------------------------------------------------------
  1141. DWORD DeleteCSCShareIfEmpty (LPCTSTR pwszFileName, SHARESTATUS shStatus)
  1142. {
  1143. DWORD Status;
  1144. WCHAR * pwszFullPath = NULL;
  1145. WCHAR * pwszCurr = NULL;
  1146. int len;
  1147. WCHAR * pwszShrEnd;
  1148. if (PathLocal == shStatus || NoCSC == shStatus)
  1149. return ERROR_SUCCESS;
  1150. if (ShareOffline == shStatus)
  1151. return ERROR_FILE_OFFLINE;
  1152. len = wcslen (pwszFileName);
  1153. if (len <= 2)
  1154. return ERROR_BAD_PATHNAME;
  1155. if (pwszFileName[0] != L'\\' || pwszFileName[1] != L'\\')
  1156. return ERROR_BAD_PATHNAME;
  1157. pwszFullPath = (WCHAR *) malloc (sizeof (WCHAR) * (len + 1));
  1158. if (NULL == pwszFullPath)
  1159. return ERROR_OUTOFMEMORY;
  1160. if (NULL == _wfullpath(pwszFullPath, pwszFileName, len + 1))
  1161. return ERROR_BAD_PATHNAME; //canonicalization was unsuccessful.
  1162. // -- rarely happens
  1163. pwszShrEnd = wcschr (pwszFullPath + 2, L'\\');
  1164. if (NULL == pwszShrEnd)
  1165. return ERROR_BAD_PATHNAME; //the path does not have the share component
  1166. pwszShrEnd++;
  1167. pwszShrEnd = wcschr (pwszShrEnd, L'\\');
  1168. if (NULL == pwszShrEnd)
  1169. {
  1170. //we already have the path in \\server\share form, so just try to
  1171. //delete the share.
  1172. if (!CSCDelete (pwszFullPath))
  1173. return GetLastError();
  1174. }
  1175. //if we are here, then we have a path longer than just \\server\share.
  1176. //so try to delete all the way up to the share name. This is necessary
  1177. //because a user might be redirected to something like
  1178. // \\server\share\folder\%username% and we wouldn't want only \\server\share
  1179. // and \\server\share\folder to be cached.
  1180. Status = ERROR_SUCCESS;
  1181. do
  1182. {
  1183. pwszCurr = wcsrchr (pwszFullPath, L'\\');
  1184. if (NULL == pwszCurr)
  1185. break;
  1186. *pwszCurr = L'\0';
  1187. if (!CSCDelete (pwszFullPath))
  1188. {
  1189. Status = GetLastError();
  1190. if (ERROR_SUCCESS == Status ||
  1191. ERROR_INVALID_PARAMETER == Status ||
  1192. ERROR_FILE_NOT_FOUND == Status ||
  1193. ERROR_PATH_NOT_FOUND == Status)
  1194. {
  1195. Status = ERROR_SUCCESS;
  1196. }
  1197. }
  1198. if (ERROR_SUCCESS != Status)
  1199. break;
  1200. } while ( pwszCurr > pwszShrEnd );
  1201. return Status;
  1202. }
  1203. //+--------------------------------------------------------------------------
  1204. //
  1205. // Function: MergePinInfo
  1206. //
  1207. // Synopsis: merges the pin info. from the source to destination
  1208. //
  1209. // Arguments: [in] pwszSource : the full path to the source
  1210. // [in] pwszDest : the full path to the destination
  1211. // [in] StatusFrom : CSC status of the source share
  1212. // [in] StatusTo : CSC status of the destination share
  1213. //
  1214. // Returns: ERROR_SUCCESS : if it was successful
  1215. // a Win32 error code otherwise
  1216. //
  1217. // History: 4/23/1999 RahulTh created
  1218. //
  1219. // Notes: the hint flags are a union of the source hint flags and
  1220. // destination hint flags. The pin count is the greater of the
  1221. // source and destination pin count
  1222. //
  1223. // Usually this function should only be called for folders. The
  1224. // CSC rename API handles files well. But this function will work
  1225. // for files as well.
  1226. //
  1227. //---------------------------------------------------------------------------
  1228. DWORD MergePinInfo (LPCTSTR pwszSource, LPCTSTR pwszDest,
  1229. SHARESTATUS StatusFrom, SHARESTATUS StatusTo)
  1230. {
  1231. BOOL bStatus;
  1232. DWORD dwSourceStat, dwDestStat;
  1233. DWORD dwSourcePinCount, dwDestPinCount;
  1234. DWORD dwSourceHints, dwDestHints;
  1235. DWORD Status = ERROR_SUCCESS;
  1236. DWORD i;
  1237. if (ShareOffline == StatusFrom || ShareOffline == StatusTo)
  1238. return ERROR_FILE_OFFLINE;
  1239. if (ShareOnline != StatusFrom || ShareOnline != StatusTo)
  1240. return ERROR_SUCCESS; //there is nothing to do if one of the shares
  1241. //is local.
  1242. if (!pwszSource || !pwszDest ||
  1243. 0 == wcslen(pwszSource) || 0 == wcslen(pwszDest))
  1244. return ERROR_BAD_PATHNAME;
  1245. bStatus = CSCQueryFileStatus (pwszSource, &dwSourceStat, &dwSourcePinCount,
  1246. &dwSourceHints);
  1247. if (!bStatus)
  1248. return GetLastError();
  1249. bStatus = CSCQueryFileStatus (pwszDest, &dwDestStat, &dwDestPinCount,
  1250. &dwDestHints);
  1251. if (!bStatus)
  1252. return GetLastError();
  1253. //first set the hint flags on the destination
  1254. if (dwDestHints != dwSourceHints)
  1255. {
  1256. bStatus = CSCPinFile (pwszDest, dwSourceHints, &dwDestStat,
  1257. &dwDestPinCount, &dwDestHints);
  1258. if (!bStatus)
  1259. Status = GetLastError(); //note: we do not bail out here. we try
  1260. //to at least merge the pin count before
  1261. //leaving
  1262. }
  1263. //now merge the pin count : there is nothing to be done if the destination
  1264. //pin count is greater than or equal to the source pin count
  1265. if (dwDestPinCount < dwSourcePinCount)
  1266. {
  1267. for (i = 0, bStatus = TRUE; i < (dwSourcePinCount - dwDestPinCount) &&
  1268. bStatus;
  1269. i++)
  1270. {
  1271. bStatus = CSCPinFile( pwszDest,
  1272. FLAG_CSC_HINT_COMMAND_ALTER_PIN_COUNT,
  1273. NULL, NULL, NULL );
  1274. }
  1275. if (!bStatus && ERROR_SUCCESS == Status)
  1276. Status = GetLastError();
  1277. }
  1278. return Status;
  1279. }
  1280. //+--------------------------------------------------------------------------
  1281. //
  1282. // Function: PinIfNecessary
  1283. //
  1284. // Synopsis: this function pins a file if necessary.
  1285. //
  1286. // Arguments: [in] pwszPath : full path of the file/folder to be pinned
  1287. // [in] shStatus : CSC status of the share.
  1288. //
  1289. // Returns: ERROR_SUCCESS if it was successful. An error code otherwise.
  1290. //
  1291. // History: 5/27/1999 RahulTh created
  1292. //
  1293. // Notes:
  1294. //
  1295. //---------------------------------------------------------------------------
  1296. DWORD PinIfNecessary (const WCHAR * pwszPath, SHARESTATUS shStatus)
  1297. {
  1298. DWORD Status = ERROR_SUCCESS;
  1299. BOOL bStatus;
  1300. DWORD dwStatus;
  1301. DWORD dwPinCount;
  1302. DWORD dwHints;
  1303. if (!pwszPath || !pwszPath[0])
  1304. return ERROR_BAD_NETPATH;
  1305. if (ShareOffline == shStatus)
  1306. return ERROR_FILE_OFFLINE;
  1307. else if (PathLocal == shStatus || NoCSC == shStatus)
  1308. return ERROR_SUCCESS;
  1309. bStatus = CSCQueryFileStatus (pwszPath, &dwStatus, &dwPinCount, &dwHints);
  1310. if (!bStatus || dwPinCount <= 0)
  1311. {
  1312. bStatus = CSCPinFile (pwszPath,
  1313. FLAG_CSC_HINT_COMMAND_ALTER_PIN_COUNT,
  1314. NULL, NULL, NULL);
  1315. if (!bStatus)
  1316. Status = GetLastError();
  1317. }
  1318. return Status;
  1319. }
  1320. //+--------------------------------------------------------------------------
  1321. //
  1322. // Function: GetCSCStatus
  1323. //
  1324. // Synopsis: given a path, finds out if it is local and if it is not
  1325. // whether it is online or offline.
  1326. //
  1327. // Arguments: [in] pwszPath : the path to the file
  1328. //
  1329. // Returns: Local/Online/Offline
  1330. //
  1331. // History: 11/20/1998 RahulTh created
  1332. //
  1333. // Notes: it is important that the path passed to this function is a
  1334. // a full path and not a relative path
  1335. //
  1336. // this function will return offline if the share is not live or
  1337. // if the share is live but CSC thinks that it is offline
  1338. //
  1339. // it will return PathLocal if the path is local or if the path
  1340. // is a network path that cannot be handled by CSC e.g. a network
  1341. // share with a pathname longer than what csc can handle or if it
  1342. // is a netware share. in this case it makes sense to return
  1343. // PathLocal because CSC won't maintain a database for these shares
  1344. // -- same as for a local path. so as far as CSC is concerned, this
  1345. // is as good as a local path.
  1346. //
  1347. //---------------------------------------------------------------------------
  1348. SHARESTATUS GetCSCStatus (const WCHAR * pwszPath)
  1349. {
  1350. WCHAR * pwszAbsPath = NULL;
  1351. WCHAR * pwszCurr = NULL;
  1352. int len;
  1353. BOOL bRetVal;
  1354. DWORD Status;
  1355. DWORD dwPinCount;
  1356. DWORD dwHints;
  1357. if (!pwszPath)
  1358. return ShareOffline; //a path must be provided
  1359. len = wcslen (pwszPath);
  1360. pwszAbsPath = (WCHAR *) malloc (sizeof (WCHAR) * (len + 1));
  1361. if (!pwszAbsPath)
  1362. {
  1363. //we are out of memory, so it is safest to return ShareOffline
  1364. //so that we can bail out of redirection.
  1365. return ShareOffline;
  1366. }
  1367. //get the absolute path
  1368. pwszCurr = _wfullpath (pwszAbsPath, pwszPath, len + 1);
  1369. if (!pwszCurr)
  1370. {
  1371. //in order for _wfullpath to fail, something really bad has to happen
  1372. //so it is best to return ShareOffline so that we can bail out of
  1373. //redirection
  1374. return ShareOffline;
  1375. }
  1376. len = wcslen (pwszAbsPath);
  1377. if (! (
  1378. (2 <= len) &&
  1379. (L'\\' == pwszAbsPath[0]) &&
  1380. (L'\\' == pwszAbsPath[1])
  1381. )
  1382. )
  1383. {
  1384. //it is a local path if it does not begin with 2 backslashes
  1385. return PathLocal;
  1386. }
  1387. //this is a UNC path; so extract the \\server\share part
  1388. pwszCurr = wcschr ( & (pwszAbsPath[2]), L'\\');
  1389. //first make sure that it is at least of the form \\server\share
  1390. //watch out for the \\server\ case
  1391. if (!pwszCurr || !pwszCurr[1])
  1392. return ShareOffline; //it is an invalid path (no share name)
  1393. //the path is of the form \\server\share
  1394. //note: the use _wfullpath automatically protects us against the \\server\\ case
  1395. pwszCurr = wcschr (&(pwszCurr[1]), L'\\');
  1396. if (pwszCurr) //if it is of the form \\server\share\...
  1397. *pwszCurr = L'\0';
  1398. //now pwszAbsPath is a share name
  1399. bRetVal = CSCCheckShareOnline (pwszAbsPath);
  1400. if (!bRetVal)
  1401. {
  1402. if (ERROR_SUCCESS != GetLastError())
  1403. {
  1404. //either there is really a problem (e.g. invalid share name) or
  1405. //it is just a share that is not handled by CSC e.g. a netware share
  1406. //or a share with a name that is longer than can be handled by CSC
  1407. //so check if the share actually exists
  1408. if (0xFFFFFFFF != GetFileAttributes(pwszAbsPath))
  1409. {
  1410. //this can still be a share that is offline since GetFileAttributes
  1411. //will return the attributes stored in the cache
  1412. Status = 0;
  1413. bRetVal = GetShareStatus (pwszAbsPath, &Status, &dwPinCount,
  1414. &dwHints);
  1415. if (! bRetVal || (! (FLAG_CSC_SHARE_STATUS_DISCONNECTED_OP & Status)))
  1416. return PathLocal; //this is simply a valid path that CSC cannot handle
  1417. else if (bRetVal &&
  1418. (FLAG_CSC_SHARE_STATUS_NO_CACHING ==
  1419. (FLAG_CSC_SHARE_STATUS_CACHING_MASK & Status)))
  1420. return PathLocal; //CSC caching is not turned on for the share.
  1421. }
  1422. }
  1423. //it is indeed an inaccessble share
  1424. return ShareOffline; //for all other cases, treat this as offline
  1425. }
  1426. else
  1427. {
  1428. //this means that the share is live, but CSC might still think that it
  1429. //is offline.
  1430. Status = 0;
  1431. bRetVal = GetShareStatus (pwszAbsPath, &Status, &dwPinCount,
  1432. &dwHints);
  1433. if (bRetVal && (FLAG_CSC_SHARE_STATUS_DISCONNECTED_OP & Status))
  1434. return ShareOffline; //CSC thinks that the share is offline
  1435. else if (bRetVal &&
  1436. (FLAG_CSC_SHARE_STATUS_NO_CACHING ==
  1437. (FLAG_CSC_SHARE_STATUS_CACHING_MASK & Status)))
  1438. return PathLocal; //CSC caching is not turned on for the share
  1439. else if (!bRetVal)
  1440. return ShareOffline;
  1441. //in all other cases, consider the share as online since
  1442. //CSCCheckShareOnline has already returned TRUE
  1443. return ShareOnline;
  1444. }
  1445. }
  1446. //+--------------------------------------------------------------------------
  1447. //
  1448. // Function: GetShareStatus
  1449. //
  1450. // Synopsis: this function is a wrapper for CSCQueryFileStatus.
  1451. // basically CSCQueryFileStatus can fail if there was never a net
  1452. // use to a share. So this function tries to create a net use to
  1453. // the share if CSCQueryFileStatus fails and then re-queries the
  1454. // file status
  1455. //
  1456. // Arguments: [in] pwszShare : the share name
  1457. // [out] pdwStatus : the share Status
  1458. // [out] pdwPinCount : the pin count
  1459. // [out] pdwHints : the hints
  1460. //
  1461. // Returns: TRUE : if everything was successful.
  1462. // FALSE : if there was an error. In this case, it GetLastError()
  1463. // will contain the specific error code.
  1464. //
  1465. // History: 5/11/1999 RahulTh created
  1466. //
  1467. // Notes: it is very important that this function be passed a share name
  1468. // it does not do any parameter validation. So under no
  1469. // circumstance should this function be passed a filename.
  1470. //
  1471. //---------------------------------------------------------------------------
  1472. BOOL GetShareStatus (const WCHAR * pwszShare, DWORD * pdwStatus,
  1473. DWORD * pdwPinCount, DWORD * pdwHints)
  1474. {
  1475. NETRESOURCE nr;
  1476. DWORD dwResult;
  1477. DWORD dwErr = NO_ERROR;
  1478. BOOL bStatus;
  1479. bStatus = CSCQueryFileStatus(pwszShare, pdwStatus, pdwPinCount, pdwHints);
  1480. if (!bStatus)
  1481. {
  1482. //try to connect to the share
  1483. ZeroMemory ((PVOID) (&nr), sizeof (NETRESOURCE));
  1484. nr.dwType = RESOURCETYPE_DISK;
  1485. nr.lpLocalName = NULL;
  1486. nr.lpRemoteName = (LPTSTR) pwszShare;
  1487. nr.lpProvider = NULL;
  1488. dwErr = WNetUseConnection(NULL, &nr, NULL, NULL, 0,
  1489. NULL, NULL, &dwResult);
  1490. if (NO_ERROR == dwErr)
  1491. {
  1492. bStatus = CSCQueryFileStatus (pwszShare, pdwStatus, pdwPinCount, pdwHints);
  1493. if (!bStatus)
  1494. dwErr = GetLastError();
  1495. else
  1496. dwErr = NO_ERROR;
  1497. WNetCancelConnection2 (pwszShare, 0, FALSE);
  1498. }
  1499. else
  1500. {
  1501. bStatus = FALSE;
  1502. }
  1503. }
  1504. SetLastError(dwErr);
  1505. return bStatus;
  1506. }
  1507. DWORD
  1508. CmdReconnect(
  1509. PWSTR ReconnectArg)
  1510. {
  1511. DWORD Error = ERROR_SUCCESS;
  1512. BOOL fRet;
  1513. if (fSwDebug == TRUE)
  1514. MyPrintf(L"CmdReconnect(%ws)\r\n", ReconnectArg);
  1515. fRet = CSCTransitionServerOnlineW(ReconnectArg);
  1516. if (fRet == FALSE)
  1517. Error = GetLastError();
  1518. return Error;
  1519. }
  1520. DWORD
  1521. CmdQueryFile(
  1522. PWSTR QueryFileArg)
  1523. {
  1524. DWORD HintFlags = 0;
  1525. DWORD PinCount = 0;
  1526. DWORD Status = 0;
  1527. DWORD Error = ERROR_SUCCESS;
  1528. BOOL fRet;
  1529. if (fSwDebug == TRUE)
  1530. MyPrintf(L"CmdQueryFile(%ws)\r\n", QueryFileArg);
  1531. fRet = CSCQueryFileStatusW(
  1532. QueryFileArg,
  1533. &Status,
  1534. &PinCount,
  1535. &HintFlags);
  1536. if (fRet == FALSE) {
  1537. Error = GetLastError();
  1538. goto AllDone;
  1539. }
  1540. if (fSwFull != TRUE) {
  1541. MyPrintf(
  1542. L"QueryFile of %ws:\r\n"
  1543. L"Status: 0x%x\r\n"
  1544. L"PinCount: %d\r\n"
  1545. L"HintFlags: 0x%x\r\n",
  1546. QueryFileArg,
  1547. Status,
  1548. PinCount,
  1549. HintFlags);
  1550. } else {
  1551. WCHAR StatusBuffer[0x100];
  1552. WCHAR HintBuffer[0x100];
  1553. if (LooksToBeAShare(QueryFileArg) == TRUE)
  1554. ShareStatusToEnglish(Status, StatusBuffer);
  1555. else
  1556. FileStatusToEnglish(Status, StatusBuffer);
  1557. HintsToEnglish(HintFlags, HintBuffer);
  1558. MyPrintf(
  1559. L"QueryFile of %ws:\r\n"
  1560. L"Status: 0x%x %ws\r\n"
  1561. L"PinCount: %d\r\n"
  1562. L"HintFlags: 0x%x %ws\r\n",
  1563. QueryFileArg,
  1564. Status,
  1565. StatusBuffer,
  1566. PinCount,
  1567. HintFlags,
  1568. HintBuffer);
  1569. }
  1570. AllDone:
  1571. return Error;
  1572. }
  1573. DWORD
  1574. CmdQueryFileEx(
  1575. PWSTR QueryFileExArg)
  1576. {
  1577. DWORD HintFlags = 0;
  1578. DWORD PinCount = 0;
  1579. DWORD Status = 0;
  1580. DWORD UserPerms = 0;
  1581. DWORD OtherPerms = 0;
  1582. DWORD Error = ERROR_SUCCESS;
  1583. BOOL fRet;
  1584. HMODULE hmodCscDll = LoadLibrary(TEXT("cscdll.dll"));
  1585. CSCQUERYFILESTATUSEXW pCSCQueryFileStatusExW = NULL;
  1586. if (fSwDebug == TRUE)
  1587. MyPrintf(L"CmdQueryFileEx(%ws)\r\n", QueryFileExArg);
  1588. if (hmodCscDll == NULL) {
  1589. Error = GetLastError();
  1590. goto AllDone;
  1591. }
  1592. pCSCQueryFileStatusExW = (CSCQUERYFILESTATUSEXW) GetProcAddress(
  1593. hmodCscDll,
  1594. "CSCQueryFileStatusExW");
  1595. if (pCSCQueryFileStatusExW == NULL) {
  1596. Error = GetLastError();
  1597. goto AllDone;
  1598. }
  1599. fRet = (pCSCQueryFileStatusExW)(
  1600. QueryFileExArg,
  1601. &Status,
  1602. &PinCount,
  1603. &HintFlags,
  1604. &UserPerms,
  1605. &OtherPerms);
  1606. if (fRet == FALSE) {
  1607. Error = GetLastError();
  1608. goto AllDone;
  1609. }
  1610. if (fSwFull != TRUE) {
  1611. MyPrintf(
  1612. L"Query of %ws:\r\n"
  1613. L"Status: 0x%x\r\n"
  1614. L"PinCount: %d\r\n"
  1615. L"HintFlags: 0x%x\r\n"
  1616. L"UserPerms: 0x%x\r\n"
  1617. L"OtherPerms: 0x%x\r\n",
  1618. QueryFileExArg,
  1619. Status,
  1620. PinCount,
  1621. HintFlags,
  1622. UserPerms,
  1623. OtherPerms);
  1624. } else {
  1625. WCHAR StatusBuffer[0x100] = {0};
  1626. WCHAR HintBuffer[0x100] = {0};
  1627. if (LooksToBeAShare(QueryFileExArg) == TRUE)
  1628. ShareStatusToEnglish(Status, StatusBuffer);
  1629. else
  1630. FileStatusToEnglish(Status, StatusBuffer);
  1631. HintsToEnglish(HintFlags, HintBuffer);
  1632. MyPrintf(
  1633. L"Query of %ws:\r\n"
  1634. L"Status: 0x%x %ws\r\n"
  1635. L"PinCount: %d\r\n"
  1636. L"HintFlags: 0x%x %ws\r\n"
  1637. L"UserPerms: 0x%x\r\n"
  1638. L"OtherPerms: 0x%x\r\n",
  1639. QueryFileExArg,
  1640. Status,
  1641. StatusBuffer,
  1642. PinCount,
  1643. HintFlags,
  1644. HintBuffer,
  1645. UserPerms,
  1646. OtherPerms);
  1647. }
  1648. AllDone:
  1649. if (hmodCscDll != NULL)
  1650. FreeLibrary(hmodCscDll);
  1651. return Error;
  1652. }
  1653. DWORD
  1654. CmdSetSpace(
  1655. PWSTR SetSpaceArg)
  1656. {
  1657. DWORD Error = ERROR_SUCCESS;
  1658. DWORD MaxSpaceHigh = 0;
  1659. DWORD MaxSpaceLow;
  1660. BOOL fRet;
  1661. if (fSwDebug == TRUE)
  1662. MyPrintf(L"CmdSetSpace(%ws)\r\n", SetSpaceArg);
  1663. swscanf(SetSpaceArg, L"%d", &MaxSpaceLow);
  1664. fRet = CSCSetMaxSpace(
  1665. MaxSpaceHigh,
  1666. MaxSpaceLow);
  1667. if (fRet == FALSE) {
  1668. Error = GetLastError();
  1669. goto AllDone;
  1670. }
  1671. CmdGetSpace();
  1672. AllDone:
  1673. return Error;
  1674. }
  1675. DWORD
  1676. CmdQueryShare(
  1677. PWSTR QueryShareArg)
  1678. {
  1679. DWORD HintFlags = 0;
  1680. DWORD PinCount = 0;
  1681. DWORD Status = 0;
  1682. DWORD UserPerms = 0;
  1683. DWORD OtherPerms = 0;
  1684. DWORD Error = ERROR_SUCCESS;
  1685. BOOL fRet;
  1686. HMODULE hmodCscDll = LoadLibrary(TEXT("cscdll.dll"));
  1687. CSCQUERYSHARESTATUSW pCSCQueryShareStatusW = NULL;
  1688. if (fSwDebug == TRUE)
  1689. MyPrintf(L"CmdQueryShare(%ws)\r\n", QueryShareArg);
  1690. if (hmodCscDll == NULL) {
  1691. Error = GetLastError();
  1692. goto AllDone;
  1693. }
  1694. pCSCQueryShareStatusW = (CSCQUERYSHARESTATUSW) GetProcAddress(
  1695. hmodCscDll,
  1696. "CSCQueryShareStatusW");
  1697. if (pCSCQueryShareStatusW == NULL) {
  1698. Error = GetLastError();
  1699. goto AllDone;
  1700. }
  1701. fRet = (pCSCQueryShareStatusW)(
  1702. QueryShareArg,
  1703. &Status,
  1704. &PinCount,
  1705. &HintFlags,
  1706. &UserPerms,
  1707. &OtherPerms);
  1708. if (fRet == FALSE) {
  1709. Error = GetLastError();
  1710. goto AllDone;
  1711. }
  1712. if (fSwFull != TRUE) {
  1713. MyPrintf(
  1714. L"Query of %ws:\r\n"
  1715. L"Status: 0x%x\r\n"
  1716. L"PinCount: %d\r\n"
  1717. L"HintFlags: 0x%x\r\n"
  1718. L"UserPerms: 0x%x\r\n"
  1719. L"OtherPerms: 0x%x\r\n",
  1720. QueryShareArg,
  1721. Status,
  1722. PinCount,
  1723. HintFlags,
  1724. UserPerms,
  1725. OtherPerms);
  1726. } else {
  1727. WCHAR StatusBuffer[0x100] = {0};
  1728. WCHAR HintBuffer[0x100] = {0};
  1729. ShareStatusToEnglish(Status, StatusBuffer);
  1730. HintsToEnglish(HintFlags, HintBuffer);
  1731. MyPrintf(
  1732. L"Query of %ws:\r\n"
  1733. L"Status: 0x%x %ws\r\n"
  1734. L"PinCount: %d\r\n"
  1735. L"HintFlags: 0x%x %ws\r\n"
  1736. L"UserPerms: 0x%x\r\n"
  1737. L"OtherPerms: 0x%x\r\n",
  1738. QueryShareArg,
  1739. Status,
  1740. StatusBuffer,
  1741. PinCount,
  1742. HintFlags,
  1743. HintBuffer,
  1744. UserPerms,
  1745. OtherPerms);
  1746. }
  1747. AllDone:
  1748. if (hmodCscDll != NULL)
  1749. FreeLibrary(hmodCscDll);
  1750. return Error;
  1751. }
  1752. DWORD
  1753. CmdMerge(
  1754. PWSTR MergeArg)
  1755. {
  1756. DWORD Error = ERROR_SUCCESS;
  1757. DWORD HowToRespond = CSCPROC_RETURN_CONTINUE; // JMH
  1758. BOOL fRet;
  1759. if (fSwDebug == TRUE)
  1760. MyPrintf(L"CmdMerge(%ws)\r\n", MergeArg);
  1761. fRet = CSCMergeShareW(MergeArg, MyCscMergeProcW, HowToRespond);
  1762. if (fRet == FALSE) {
  1763. Error = GetLastError();
  1764. goto AllDone;
  1765. }
  1766. fRet = CSCTransitionServerOnlineW(MergeArg);
  1767. if (fRet == FALSE)
  1768. Error = GetLastError();
  1769. AllDone:
  1770. return Error;
  1771. }
  1772. DWORD
  1773. CmdMove(
  1774. PWSTR MoveArg)
  1775. {
  1776. DWORD Error = ERROR_FILE_NOT_FOUND;
  1777. LPWSTR lpszTempName = NULL;
  1778. if (!CSCCopyReplicaW(MoveArg, &lpszTempName)) {
  1779. Error = GetLastError();
  1780. } else {
  1781. Error = ERROR_SUCCESS;
  1782. }
  1783. if (Error == ERROR_SUCCESS)
  1784. MyPrintf(L"Copy is %ws\r\n", lpszTempName);
  1785. return Error;
  1786. }
  1787. DWORD
  1788. CmdEncryptDecrypt(
  1789. BOOL fEncrypt)
  1790. {
  1791. DWORD Error = ERROR_SUCCESS;
  1792. DWORD EncryptDecryptType = 0;
  1793. BOOL fRet;
  1794. HMODULE hmodCscDll = LoadLibrary(TEXT("cscdll.dll"));
  1795. CSCENCRYPTDECRYPTDATABASE pCSCEncryptDecryptDatabase = NULL;
  1796. if (fSwDebug == TRUE)
  1797. MyPrintf(L"CmdEncryptDecrypt(%ws)\r\n", fEncrypt == TRUE ? L"Encrypt" : L"Decrypt");
  1798. if (hmodCscDll == NULL) {
  1799. Error = GetLastError();
  1800. goto AllDone;
  1801. }
  1802. pCSCEncryptDecryptDatabase = (CSCENCRYPTDECRYPTDATABASE) GetProcAddress(
  1803. hmodCscDll,
  1804. "CSCEncryptDecryptDatabase");
  1805. if (pCSCEncryptDecryptDatabase == NULL) {
  1806. Error = GetLastError();
  1807. goto AllDone;
  1808. }
  1809. fRet = (pCSCEncryptDecryptDatabase)(fEncrypt, MyEncryptDecryptProcW, EncryptDecryptType);
  1810. if (fRet == FALSE) {
  1811. Error = GetLastError();
  1812. goto AllDone;
  1813. }
  1814. AllDone:
  1815. if (hmodCscDll != NULL)
  1816. FreeLibrary(hmodCscDll);
  1817. if (fSwDebug == TRUE)
  1818. MyPrintf(L"CmdEncryptDecrypt exit %d\r\n", Error);
  1819. return Error;
  1820. }
  1821. DWORD
  1822. CmdFill(
  1823. PWSTR FillArg)
  1824. {
  1825. DWORD Error = ERROR_SUCCESS;
  1826. DWORD HowToRespond = CSCPROC_RETURN_CONTINUE;
  1827. BOOL fRet;
  1828. if (fSwDebug == TRUE)
  1829. MyPrintf(L"CmdFill(%ws, %d)\r\n", FillArg, fSwFull);
  1830. fRet = CSCFillSparseFilesW(FillArg, fSwFull, MyCscFillProcW, HowToRespond);
  1831. if (fRet == FALSE) {
  1832. Error = GetLastError();
  1833. }
  1834. return Error;
  1835. }
  1836. DWORD
  1837. CmdCheck(
  1838. PWSTR CheckArg)
  1839. {
  1840. DWORD Error = ERROR_SUCCESS;
  1841. DWORD Speed = 0;
  1842. BOOL fOnline = FALSE;
  1843. if (fSwDebug == TRUE)
  1844. MyPrintf(L"CmdCheck(%ws)\r\n", CheckArg);
  1845. fOnline = CSCCheckShareOnlineExW(CheckArg, &Speed);
  1846. MyPrintf(
  1847. L"%ws is %s\r\n",
  1848. CheckArg,
  1849. (fOnline == FALSE) ? L"Offline" : L"Online");
  1850. return Error;
  1851. }
  1852. DWORD
  1853. CmdDBStatus(
  1854. VOID)
  1855. {
  1856. GLOBALSTATUS sGS = {0};
  1857. ULONG DBStatus = 0;
  1858. ULONG DBErrorFlags = 0;
  1859. BOOL bResult;
  1860. HANDLE hDBShadow = INVALID_HANDLE_VALUE;
  1861. ULONG junk;
  1862. ULONG Status = 0;
  1863. if (fSwDebug == TRUE)
  1864. MyPrintf(L"CmdDBStatus()\r\n");
  1865. hDBShadow = CreateFile(
  1866. L"\\\\.\\shadow",
  1867. GENERIC_READ | GENERIC_WRITE,
  1868. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1869. NULL,
  1870. OPEN_EXISTING,
  1871. 0,
  1872. NULL);
  1873. if (hDBShadow == INVALID_HANDLE_VALUE) {
  1874. MyPrintf(L"CmdDBStatus:Failed open of shadow device\r\n");
  1875. Status = GetLastError();
  1876. goto AllDone;
  1877. }
  1878. bResult = DeviceIoControl(
  1879. hDBShadow, // device
  1880. IOCTL_GETGLOBALSTATUS, // control code
  1881. (LPVOID)&sGS, // in buffer
  1882. 0, // inbuffer size
  1883. NULL, // out buffer
  1884. 0, // out buffer size
  1885. &junk, // bytes returned
  1886. NULL); // overlapped
  1887. if (!bResult) {
  1888. MyPrintf(L"CmdDBStatus:DeviceIoControl IOCTL_GETGLOBALSTATUS failed\n");
  1889. Status = GetLastError();
  1890. goto AllDone;
  1891. }
  1892. DBStatus = sGS.sST.uFlags;
  1893. DBErrorFlags = sGS.uDatabaseErrorFlags;
  1894. if (DBStatus & FLAG_DATABASESTATUS_DIRTY)
  1895. MyPrintf(L"FLAG_DATABASESTATUS_DIRTY\r\n");
  1896. if (DBStatus & FLAG_DATABASESTATUS_UNENCRYPTED)
  1897. MyPrintf(L"FLAG_DATABASESTATUS_UNENCRYPTED\r\n");
  1898. if (DBStatus & FLAG_DATABASESTATUS_PARTIALLY_UNENCRYPTED)
  1899. MyPrintf(L"FLAG_DATABASESTATUS_PARTIALLY_UNENCRYPTED\r\n");
  1900. if (DBStatus & FLAG_DATABASESTATUS_ENCRYPTED)
  1901. MyPrintf(L"FLAG_DATABASESTATUS_ENCRYPTED\r\n");
  1902. if (DBStatus & FLAG_DATABASESTATUS_PARTIALLY_ENCRYPTED)
  1903. MyPrintf(L"FLAG_DATABASESTATUS_PARTIALLY_ENCRYPTED\r\n");
  1904. MyPrintf(L"Database Error Flags : 0x%x\r\n", DBErrorFlags);
  1905. AllDone:
  1906. if (fSwDebug == TRUE)
  1907. MyPrintf(L"CmdDBStatus exit %d\r\n", Status);
  1908. if (hDBShadow != INVALID_HANDLE_VALUE)
  1909. CloseHandle(hDBShadow);
  1910. return Status;
  1911. }
  1912. DWORD
  1913. CmdPurge(
  1914. PWSTR PurgeArg)
  1915. {
  1916. ULONG nFiles = 0;
  1917. ULONG nYoungFiles = 0;
  1918. ULONG Status = ERROR_SUCCESS;
  1919. ULONG Timeout = 120;
  1920. BOOL fRet = FALSE;
  1921. HMODULE hmodCscDll = LoadLibrary(TEXT("cscdll.dll"));
  1922. CSCPURGEUNPINNEDFILES pCSCPurgeUnpinnedFiles = NULL;
  1923. if (fSwDebug == TRUE)
  1924. MyPrintf(L"CmdPurge(%ws)\r\n", PurgeArg);
  1925. if (hmodCscDll == NULL) {
  1926. Status = GetLastError();
  1927. goto AllDone;
  1928. }
  1929. pCSCPurgeUnpinnedFiles = (CSCPURGEUNPINNEDFILES) GetProcAddress(
  1930. hmodCscDll,
  1931. "CSCPurgeUnpinnedFiles");
  1932. if (pCSCPurgeUnpinnedFiles == NULL) {
  1933. Status = GetLastError();
  1934. goto AllDone;
  1935. }
  1936. if (PurgeArg != NULL)
  1937. swscanf(PurgeArg, L"%d", &Timeout);
  1938. if (fSwDebug == TRUE)
  1939. MyPrintf(L"Timeout=%d seconds\r\n", Timeout);
  1940. fRet = (pCSCPurgeUnpinnedFiles)(Timeout, &nFiles, &nYoungFiles);
  1941. if (fRet == FALSE) {
  1942. Status = GetLastError();
  1943. goto AllDone;
  1944. }
  1945. MyPrintf(L"nFiles = %d nYoungFiles=%d\n", nFiles, nYoungFiles);
  1946. AllDone:
  1947. if (hmodCscDll != NULL)
  1948. FreeLibrary(hmodCscDll);
  1949. if (fSwDebug == TRUE)
  1950. MyPrintf(L"CmdPurge exit %d\r\n", Status);
  1951. return Status;
  1952. }
  1953. DWORD
  1954. CmdPQEnum(
  1955. VOID)
  1956. {
  1957. PQPARAMS PQP = {0};
  1958. BOOL bResult;
  1959. HANDLE hDBShadow = INVALID_HANDLE_VALUE;
  1960. ULONG junk;
  1961. ULONG Status = 0;
  1962. if (fSwDebug == TRUE)
  1963. MyPrintf(L"CmdPQEnum()\r\n");
  1964. hDBShadow = CreateFile(
  1965. L"\\\\.\\shadow",
  1966. GENERIC_READ | GENERIC_WRITE,
  1967. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1968. NULL,
  1969. OPEN_EXISTING,
  1970. 0,
  1971. NULL);
  1972. if (hDBShadow == INVALID_HANDLE_VALUE) {
  1973. MyPrintf(L"CmdPQEnum:Failed open of shadow device\r\n");
  1974. Status = GetLastError();
  1975. goto AllDone;
  1976. }
  1977. MyPrintf(L" POS SHARE DIR SHADOW STATUS REFPRI HPRI HINTFLG HINTPRI VER\r\n");
  1978. bResult = DeviceIoControl(
  1979. hDBShadow, // device
  1980. IOCTL_SHADOW_BEGIN_PQ_ENUM, // control code
  1981. (LPVOID)&PQP, // in buffer
  1982. 0, // inbuffer size
  1983. NULL, // out buffer
  1984. 0, // out buffer size
  1985. &junk, // bytes returned
  1986. NULL); // overlapped
  1987. if (!bResult) {
  1988. MyPrintf(L"CmdPQEnum:DeviceIoControl IOCTL_SHADOW_BEGIN_PQ_ENUM failed\n");
  1989. Status = GetLastError();
  1990. goto AllDone;
  1991. }
  1992. do {
  1993. bResult = DeviceIoControl(
  1994. hDBShadow, // device
  1995. IOCTL_SHADOW_NEXT_PRI_SHADOW, // control code
  1996. (LPVOID)&PQP, // in buffer
  1997. 0, // inbuffer size
  1998. NULL, // out buffer
  1999. 0, // out buffer size
  2000. &junk, // bytes returned
  2001. NULL); // overlapped
  2002. if (bResult) {
  2003. MyPrintf(L"%5d %5x %8x %8x %8x %6d %6x %7d %7d %4d\r\n",
  2004. PQP.uPos,
  2005. PQP.hShare,
  2006. PQP.hDir,
  2007. PQP.hShadow,
  2008. PQP.ulStatus,
  2009. PQP.ulRefPri,
  2010. PQP.ulIHPri,
  2011. PQP.ulHintFlags,
  2012. PQP.ulHintPri,
  2013. PQP.dwPQVersion);
  2014. }
  2015. } while (bResult && PQP.uPos != 0);
  2016. bResult = DeviceIoControl(
  2017. hDBShadow, // device
  2018. IOCTL_SHADOW_END_PQ_ENUM, // control code
  2019. (LPVOID)&PQP, // in buffer
  2020. 0, // inbuffer size
  2021. NULL, // out buffer
  2022. 0, // out buffer size
  2023. &junk, // bytes returned
  2024. NULL); // overlapped
  2025. AllDone:
  2026. if (fSwDebug == TRUE)
  2027. MyPrintf(L"CmdPQEnum exit %d\r\n", Status);
  2028. if (hDBShadow != INVALID_HANDLE_VALUE)
  2029. CloseHandle(hDBShadow);
  2030. return Status;
  2031. }
  2032. LPWSTR
  2033. ConvertGmtTimeToString(
  2034. FILETIME Time,
  2035. LPWSTR OutputBuffer)
  2036. {
  2037. FILETIME LocalTime;
  2038. SYSTEMTIME SystemTime;
  2039. static FILETIME ftNone = {0, 0};
  2040. if (memcmp(&Time, &ftNone, sizeof(FILETIME)) == 0) {
  2041. wsprintf (OutputBuffer, L"<none>");
  2042. } else {
  2043. FileTimeToLocalFileTime( &Time , &LocalTime );
  2044. FileTimeToSystemTime( &LocalTime, &SystemTime );
  2045. wsprintf(
  2046. OutputBuffer,
  2047. L"%02u/%02u/%04u %02u:%02u:%02u ",
  2048. SystemTime.wMonth,
  2049. SystemTime.wDay,
  2050. SystemTime.wYear,
  2051. SystemTime.wHour,
  2052. SystemTime.wMinute,
  2053. SystemTime.wSecond );
  2054. }
  2055. return( OutputBuffer );
  2056. }
  2057. VOID
  2058. DumpCscEntryInfo(
  2059. LPWSTR Path,
  2060. PWIN32_FIND_DATA Find32,
  2061. DWORD Status,
  2062. DWORD PinCount,
  2063. DWORD HintFlags,
  2064. PFILETIME OrgTime)
  2065. {
  2066. WCHAR TimeBuf1[40];
  2067. WCHAR TimeBuf2[40];
  2068. FILE *fp = NULL;
  2069. if (fSwTouch == TRUE) {
  2070. if (Path == NULL) {
  2071. wsprintf(NameBuf, L"%ws", Find32->cFileName);
  2072. } else {
  2073. wsprintf(NameBuf, L"%ws\\%ws", Path, Find32->cFileName);
  2074. }
  2075. MyPrintf(L"%ws\r\n", NameBuf);
  2076. if ((Find32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
  2077. fp = _wfopen(NameBuf, L"rb");
  2078. if (fp != NULL)
  2079. fclose(fp);
  2080. }
  2081. } else if (fSwFull == TRUE) {
  2082. WCHAR StatusBuffer[0x100];
  2083. WCHAR HintBuffer[0x100];
  2084. if (Path != NULL)
  2085. MyPrintf(L"Directory %ws\r\n", Path);
  2086. ConvertGmtTimeToString(Find32->ftLastWriteTime, TimeBuf1);
  2087. MyPrintf(
  2088. L"LFN: %s\r\n"
  2089. L"SFN: %s\r\n"
  2090. L"Attr: 0x%x\r\n"
  2091. L"Size: 0x%x:0x%x\r\n"
  2092. L"LastWriteTime: %ws\r\n",
  2093. Find32->cFileName,
  2094. Find32->cAlternateFileName,
  2095. Find32->dwFileAttributes,
  2096. Find32->nFileSizeHigh, Find32->nFileSizeLow,
  2097. TimeBuf1);
  2098. if (OrgTime) {
  2099. ConvertGmtTimeToString(*OrgTime, TimeBuf1);
  2100. MyPrintf(L"ORGTime: %ws\r\n", TimeBuf1);
  2101. }
  2102. StatusBuffer[0] = L'\0';
  2103. HintBuffer[0] = L'\0';
  2104. if (Path == NULL) {
  2105. ShareStatusToEnglish(Status, StatusBuffer);
  2106. HintsToEnglish(HintFlags, HintBuffer);
  2107. } else {
  2108. if (LooksToBeAShare(Path) == TRUE)
  2109. ShareStatusToEnglish(Status, StatusBuffer);
  2110. else
  2111. FileStatusToEnglish(Status, StatusBuffer);
  2112. HintsToEnglish(HintFlags, HintBuffer);
  2113. }
  2114. MyPrintf(
  2115. L"Status: 0x%x %ws\r\n"
  2116. L"PinCount: %d\r\n"
  2117. L"HintFlags: 0x%x %ws\r\n\r\n",
  2118. Status,
  2119. StatusBuffer,
  2120. PinCount,
  2121. HintFlags,
  2122. HintBuffer);
  2123. } else {
  2124. if (Path == NULL) {
  2125. MyPrintf(L"%ws\r\n", Find32->cFileName);
  2126. } else {
  2127. MyPrintf(L"%ws\\%ws\r\n", Path, Find32->cFileName);
  2128. }
  2129. MyPrintf(L" Attr=0x%x Size=0x%x:0x%x Status=0x%x PinCount=%d HintFlags=0x%x\r\n",
  2130. Find32->dwFileAttributes,
  2131. Find32->nFileSizeHigh, Find32->nFileSizeLow,
  2132. Status,
  2133. PinCount,
  2134. HintFlags);
  2135. ConvertGmtTimeToString(Find32->ftLastWriteTime, TimeBuf1);
  2136. if (OrgTime)
  2137. ConvertGmtTimeToString(*OrgTime, TimeBuf2);
  2138. else
  2139. wcscpy(TimeBuf2, L"<none>");
  2140. MyPrintf(L" LastWriteTime: %ws OrgTime: %ws\r\n",
  2141. TimeBuf1,
  2142. TimeBuf2);
  2143. MyPrintf(L"\r\n");
  2144. }
  2145. }
  2146. DWORD
  2147. CmdEnum(
  2148. PWSTR EnumArg)
  2149. {
  2150. HANDLE hFind;
  2151. DWORD Error = ERROR_SUCCESS;
  2152. DWORD Status = 0;
  2153. DWORD PinCount = 0;
  2154. DWORD HintFlags = 0;
  2155. FILETIME ftOrgTime = {0};
  2156. WIN32_FIND_DATAW sFind32 = {0};
  2157. WCHAR FullPath[MAX_PATH];
  2158. if (fSwDebug == TRUE)
  2159. MyPrintf(L"CmdEnum(%ws)\r\n", EnumArg);
  2160. hFind = CSCFindFirstFileW(EnumArg, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime);
  2161. if (hFind == INVALID_HANDLE_VALUE) {
  2162. Error = GetLastError();
  2163. goto AllDone;
  2164. }
  2165. DumpCscEntryInfo(EnumArg, &sFind32, Status, PinCount, HintFlags, &ftOrgTime);
  2166. if (fSwRecurse == TRUE && (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  2167. if (EnumArg != NULL) {
  2168. wcscpy(FullPath, EnumArg);
  2169. wcscat(FullPath, L"\\");
  2170. } else {
  2171. wcscpy(FullPath, L"");
  2172. }
  2173. wcscat(FullPath, sFind32.cFileName);
  2174. CmdEnum(FullPath);
  2175. }
  2176. while (CSCFindNextFileW(hFind, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime)) {
  2177. DumpCscEntryInfo(EnumArg, &sFind32, Status, PinCount, HintFlags, &ftOrgTime);
  2178. if (fSwRecurse == TRUE && (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  2179. if (EnumArg != NULL) {
  2180. wcscpy(FullPath, EnumArg);
  2181. wcscat(FullPath, L"\\");
  2182. } else {
  2183. wcscpy(FullPath, L"");
  2184. }
  2185. wcscat(FullPath, sFind32.cFileName);
  2186. CmdEnum(FullPath);
  2187. }
  2188. }
  2189. CSCFindClose(hFind);
  2190. AllDone:
  2191. return (Error);
  2192. }
  2193. DWORD
  2194. CmdEnumForStats(
  2195. PWSTR EnumForStatsArg)
  2196. {
  2197. DWORD Error = ERROR_SUCCESS;
  2198. DWORD EnumForStatsType = 0;
  2199. BOOL fRet;
  2200. if (fSwDebug == TRUE)
  2201. MyPrintf(L"CmdEnumForStats()\r\n");
  2202. fRet = CSCEnumForStatsW(EnumForStatsArg, MyEnumForStatsProcW, EnumForStatsType);
  2203. if (fRet == FALSE) {
  2204. Error = GetLastError();
  2205. goto AllDone;
  2206. }
  2207. AllDone:
  2208. if (fSwDebug == TRUE)
  2209. MyPrintf(L"CmdEnumForStats exit %d\r\n", Error);
  2210. return Error;
  2211. }
  2212. DWORD
  2213. CmdDelete(
  2214. PWSTR DeleteArg)
  2215. {
  2216. DWORD Error = ERROR_SUCCESS;
  2217. DWORD Status = 0;
  2218. DWORD PinCount = 0;
  2219. DWORD HintFlags = 0;
  2220. FILETIME ftOrgTime = {0};
  2221. BOOL fResult;
  2222. HANDLE hFind;
  2223. WIN32_FIND_DATAW sFind32 = {0};
  2224. WCHAR FullPath[MAX_PATH];
  2225. if (fSwDebug == TRUE)
  2226. MyPrintf(L"CmdDelete(%ws)\r\n", DeleteArg);
  2227. //
  2228. // Non-recursive delete
  2229. //
  2230. if (fSwRecurse == FALSE) {
  2231. fResult = CSCDeleteW(DeleteArg);
  2232. if (fResult == FALSE)
  2233. Error = GetLastError();
  2234. goto AllDone;
  2235. }
  2236. //
  2237. // Delete recursively, using eumeration
  2238. //
  2239. hFind = CSCFindFirstFileW(DeleteArg, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime);
  2240. if (hFind == INVALID_HANDLE_VALUE) {
  2241. Error = GetLastError();
  2242. goto AllDone;
  2243. }
  2244. if (DeleteArg != NULL) {
  2245. wcscpy(FullPath, DeleteArg);
  2246. wcscat(FullPath, L"\\");
  2247. } else {
  2248. wcscpy(FullPath, L"");
  2249. }
  2250. wcscat(FullPath, sFind32.cFileName);
  2251. if (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  2252. CmdDelete(FullPath);
  2253. MyPrintf(L"CSCDeleteW(%ws) -> %d\r\n", FullPath, CSCDeleteW(FullPath));
  2254. while (CSCFindNextFileW(hFind, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime)) {
  2255. if (DeleteArg != NULL) {
  2256. wcscpy(FullPath, DeleteArg);
  2257. wcscat(FullPath, L"\\");
  2258. } else {
  2259. wcscpy(FullPath, L"");
  2260. }
  2261. wcscat(FullPath, sFind32.cFileName);
  2262. if (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  2263. CmdDelete(FullPath);
  2264. MyPrintf(L"CSCDeleteW(%ws) -> %d\r\n", FullPath, CSCDeleteW(FullPath));
  2265. }
  2266. CSCFindClose(hFind);
  2267. AllDone:
  2268. return (Error);
  2269. }
  2270. DWORD
  2271. CmdDeleteShadow(
  2272. PWSTR DeleteShadowArg)
  2273. {
  2274. HSHADOW hDir;
  2275. HSHADOW hShadow;
  2276. SHADOWINFO sSI;
  2277. BOOL bResult;
  2278. HANDLE hDBShadow = INVALID_HANDLE_VALUE;
  2279. ULONG junk;
  2280. ULONG Status = 0;
  2281. ULONG hShare;
  2282. if (fSwDebug == TRUE)
  2283. MyPrintf(L"CmdDeleteShadow(%ws)\r\n", DeleteShadowArg);
  2284. hDBShadow = CreateFile(
  2285. L"\\\\.\\shadow",
  2286. GENERIC_READ | GENERIC_WRITE,
  2287. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2288. NULL,
  2289. OPEN_EXISTING,
  2290. 0,
  2291. NULL);
  2292. if (hDBShadow == INVALID_HANDLE_VALUE) {
  2293. MyPrintf(L"CmdDeleteShadow:Failed open of shadow device\r\n");
  2294. Status = GetLastError();
  2295. goto AllDone;
  2296. }
  2297. swscanf(DeleteShadowArg, L"0x%x:0x%x", &hDir, &hShadow);
  2298. if (fSwDebug == TRUE)
  2299. MyPrintf(L"CmdDeleteShadow: hDir:0x%x hShadow:0x%x\r\n", hDir, hShadow);
  2300. memset(&sSI, 0, sizeof(SHADOWINFO));
  2301. sSI.hDir = hDir;
  2302. sSI.hShadow = hShadow;
  2303. bResult = DeviceIoControl(
  2304. hDBShadow, // device
  2305. IOCTL_SHADOW_DELETE, // control code
  2306. (LPVOID)&sSI, // in buffer
  2307. 0, // inbuffer size
  2308. NULL, // out buffer
  2309. 0, // out buffer size
  2310. &junk, // bytes returned
  2311. NULL); // overlapped
  2312. if (!bResult) {
  2313. MyPrintf(
  2314. L"CmdDeleteShadow:DeviceIoControl IOCTL_SHADOW_DELETE failed 0x%x\n",
  2315. sSI.dwError);
  2316. Status = sSI.dwError;
  2317. goto AllDone;
  2318. }
  2319. AllDone:
  2320. if (fSwDebug == TRUE)
  2321. MyPrintf(L"CmdDeleteShadow exit %d\r\n", Status);
  2322. if (hDBShadow != INVALID_HANDLE_VALUE)
  2323. CloseHandle(hDBShadow);
  2324. return Status;
  2325. }
  2326. DWORD
  2327. CmdPinUnPin(
  2328. BOOL fPin,
  2329. PWSTR PinArg)
  2330. {
  2331. BOOL fRet;
  2332. HANDLE hFind;
  2333. DWORD Error = ERROR_SUCCESS;
  2334. DWORD Status = 0;
  2335. DWORD PinCount = 0;
  2336. DWORD HintFlags = 0;
  2337. FILETIME ftOrgTime = {0};
  2338. WIN32_FIND_DATAW sFind32 = {0};
  2339. WCHAR FullPath[MAX_PATH];
  2340. if (fSwDebug == TRUE)
  2341. MyPrintf(L"CmdPinUnPin(%d,%ws)\r\n", fPin, PinArg);
  2342. if (fSwUser == TRUE && fSwSystem == TRUE) {
  2343. MyPrintf(L"Can not use both /SYSTEM and /USER\r\n");
  2344. goto AllDone;
  2345. }
  2346. if (fSwUser == TRUE) {
  2347. if (fSwInherit == TRUE)
  2348. HintFlags |= FLAG_CSC_HINT_PIN_INHERIT_USER;
  2349. else
  2350. HintFlags |= FLAG_CSC_HINT_PIN_USER;
  2351. }
  2352. if (fSwSystem == TRUE) {
  2353. if (fSwInherit == TRUE)
  2354. HintFlags |= FLAG_CSC_HINT_PIN_INHERIT_SYSTEM;
  2355. else
  2356. HintFlags |= FLAG_CSC_HINT_PIN_SYSTEM;
  2357. }
  2358. if (fSwRecurse == TRUE && fPin == TRUE) {
  2359. MyPrintf(L"Can not pin recursively.\r\n");
  2360. goto AllDone;
  2361. }
  2362. //
  2363. // Pin/Unpin one file
  2364. //
  2365. if (fSwRecurse == FALSE) {
  2366. if (fPin == TRUE) {
  2367. fRet = CSCPinFileW(PinArg, HintFlags, &Status, &PinCount, &HintFlags);
  2368. } else {
  2369. fRet = CSCUnpinFileW(PinArg, HintFlags, &Status, &PinCount, &HintFlags);
  2370. }
  2371. if (fRet == FALSE) {
  2372. Error = GetLastError();
  2373. goto AllDone;
  2374. }
  2375. MyPrintf(
  2376. L"%ws of %ws:\r\n"
  2377. L"Status: 0x%x\r\n"
  2378. L"PinCount: %d\r\n"
  2379. L"HintFlags: 0x%x\r\n",
  2380. fPin ? L"Pin" : L"Unpin",
  2381. PinArg,
  2382. Status,
  2383. PinCount,
  2384. HintFlags);
  2385. goto AllDone;
  2386. }
  2387. //
  2388. // Unpin recursively, using eumeration
  2389. //
  2390. hFind = CSCFindFirstFileW(PinArg, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime);
  2391. if (hFind == INVALID_HANDLE_VALUE) {
  2392. Error = GetLastError();
  2393. goto AllDone;
  2394. }
  2395. if (PinArg != NULL) {
  2396. wcscpy(FullPath, PinArg);
  2397. wcscat(FullPath, L"\\");
  2398. } else {
  2399. wcscpy(FullPath, L"");
  2400. }
  2401. wcscat(FullPath, sFind32.cFileName);
  2402. if (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  2403. CmdPinUnPin(fPin, FullPath);
  2404. fRet = CSCUnpinFileW(FullPath, HintFlags, &Status, &PinCount, &HintFlags);
  2405. MyPrintf(L"CSCUnpinFile(%ws) -> %d\r\n", FullPath, fRet);
  2406. while (CSCFindNextFileW(hFind, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime)) {
  2407. if (PinArg != NULL) {
  2408. wcscpy(FullPath, PinArg);
  2409. wcscat(FullPath, L"\\");
  2410. } else {
  2411. wcscpy(FullPath, L"");
  2412. }
  2413. wcscat(FullPath, sFind32.cFileName);
  2414. if (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  2415. CmdPinUnPin(fPin, FullPath);
  2416. fRet = CSCUnpinFileW(FullPath, HintFlags, &Status, &PinCount, &HintFlags);
  2417. MyPrintf(L"CSCUnpinFile(%ws) -> %d\r\n", FullPath, fRet);
  2418. }
  2419. CSCFindClose(hFind);
  2420. AllDone:
  2421. return Error;
  2422. }
  2423. DWORD
  2424. MyCscMergeProcW(
  2425. LPCWSTR lpszFullPath,
  2426. DWORD dwStatus,
  2427. DWORD dwHintFlags,
  2428. DWORD dwPinCount,
  2429. WIN32_FIND_DATAW *lpFind32,
  2430. DWORD dwReason,
  2431. DWORD dwParam1,
  2432. DWORD dwParam2,
  2433. DWORD_PTR dwContext)
  2434. {
  2435. if (dwReason == CSCPROC_REASON_BEGIN || dwReason == CSCPROC_REASON_MORE_DATA) {
  2436. if (dwReason == CSCPROC_REASON_BEGIN) {
  2437. MyPrintf( L"BEGIN[%ws][%d/%d]",
  2438. (lpszFullPath) ? lpszFullPath : L"None",
  2439. dwParam1,
  2440. dwParam2);
  2441. } else if (dwReason == CSCPROC_REASON_MORE_DATA) {
  2442. MyPrintf( L"MORE_DATA[%ws][%d/%d]",
  2443. (lpszFullPath) ? lpszFullPath : L"None",
  2444. dwParam1,
  2445. dwParam2);
  2446. }
  2447. if (fSwAbort) {
  2448. MyPrintf(L":Abort\r\n");
  2449. return CSCPROC_RETURN_ABORT;
  2450. } else if (fSwSkip) {
  2451. MyPrintf(L":Skip\r\n");
  2452. return CSCPROC_RETURN_SKIP;
  2453. } else if (fSwRetry) {
  2454. MyPrintf(L"Retry\r\n");
  2455. return CSCPROC_RETURN_RETRY;
  2456. } else if (fSwAsk) {
  2457. MyPrintf(L" - (R)etry/(A)bort/(S)kip/(C)ontinue:");
  2458. return CscMergeFillAsk(lpszFullPath);
  2459. } else {
  2460. MyPrintf(L"Continue\r\n");
  2461. return (DWORD)dwContext;
  2462. }
  2463. }
  2464. MyPrintf( L"END[%ws]:", (lpszFullPath) ? lpszFullPath : L"None");
  2465. if (dwParam2 == ERROR_SUCCESS) {
  2466. MyPrintf(L"SUCCEEDED\r\n");
  2467. } else {
  2468. MyPrintf(L"ERROR=%d \r\n", dwParam2);
  2469. }
  2470. return (DWORD)dwContext;
  2471. }
  2472. DWORD
  2473. MyCscFillProcW(
  2474. LPCWSTR lpszFullPath,
  2475. DWORD dwStatus,
  2476. DWORD dwHintFlags,
  2477. DWORD dwPinCount,
  2478. WIN32_FIND_DATAW *lpFind32,
  2479. DWORD dwReason,
  2480. DWORD dwParam1,
  2481. DWORD dwParam2,
  2482. DWORD_PTR dwContext)
  2483. {
  2484. if (dwReason == CSCPROC_REASON_BEGIN || dwReason == CSCPROC_REASON_MORE_DATA) {
  2485. if (dwReason == CSCPROC_REASON_BEGIN) {
  2486. MyPrintf( L"BEGIN[%ws][%d/%d]",
  2487. (lpszFullPath) ? lpszFullPath : L"None",
  2488. dwParam1,
  2489. dwParam2);
  2490. } else if (dwReason == CSCPROC_REASON_MORE_DATA) {
  2491. MyPrintf( L"MORE_DATA[%ws][%d/%d]",
  2492. (lpszFullPath) ? lpszFullPath : L"None",
  2493. dwParam1,
  2494. dwParam2);
  2495. }
  2496. if (fSwAbort) {
  2497. MyPrintf(L":Abort\r\n");
  2498. return CSCPROC_RETURN_ABORT;
  2499. } else if (fSwSkip) {
  2500. MyPrintf(L":Skip\r\n");
  2501. return CSCPROC_RETURN_SKIP;
  2502. } else if (fSwRetry) {
  2503. MyPrintf(L"Retry\r\n");
  2504. return CSCPROC_RETURN_RETRY;
  2505. } else if (fSwAsk) {
  2506. MyPrintf(L" - (R)etry/(A)bort/(S)kip/(C)ontinue:");
  2507. return CscMergeFillAsk(lpszFullPath);
  2508. } else {
  2509. MyPrintf(L"Continue\r\n");
  2510. return (DWORD)dwContext;
  2511. }
  2512. }
  2513. MyPrintf( L"END[%ws]:", (lpszFullPath) ? lpszFullPath : L"None");
  2514. if (dwParam2 == ERROR_SUCCESS) {
  2515. MyPrintf(L"SUCCEEDED\r\n");
  2516. } else {
  2517. MyPrintf(L"ERROR=%d \r\n", dwParam2);
  2518. }
  2519. return (DWORD)dwContext;
  2520. }
  2521. DWORD
  2522. CscMergeFillAsk(LPCWSTR lpszFullPath)
  2523. {
  2524. WCHAR wch;
  2525. ULONG ulid;
  2526. LONG cnt;
  2527. WCHAR rgwch[256];
  2528. PWCHAR lpBuff = NULL;
  2529. do {
  2530. lpBuff = rgwch;
  2531. memset(rgwch, 0, sizeof(rgwch));
  2532. if (!fgetws(rgwch, sizeof(rgwch)/sizeof(WCHAR), stdin))
  2533. break;
  2534. // Chop leading blanks
  2535. if (lpBuff != NULL)
  2536. while (*lpBuff != L'\0' && *lpBuff == L' ')
  2537. lpBuff++;
  2538. cnt = swscanf(lpBuff, L"%c", &wch);
  2539. if (!cnt)
  2540. continue;
  2541. switch (wch) {
  2542. case L's': case L'S':
  2543. return CSCPROC_RETURN_SKIP;
  2544. case L'c': case L'C':
  2545. return CSCPROC_RETURN_CONTINUE;
  2546. case L'a': case L'A':
  2547. return CSCPROC_RETURN_ABORT;
  2548. case L'r': case L'R':
  2549. return CSCPROC_RETURN_RETRY;
  2550. }
  2551. } while (1);
  2552. return CSCPROC_RETURN_CONTINUE;
  2553. }
  2554. DWORD
  2555. MyEncryptDecryptProcW(
  2556. LPCWSTR lpszFullPath,
  2557. DWORD dwStatus,
  2558. DWORD dwHintFlags,
  2559. DWORD dwPinCount,
  2560. WIN32_FIND_DATAW *lpFind32,
  2561. DWORD dwReason,
  2562. DWORD dwParam1,
  2563. DWORD dwParam2,
  2564. DWORD_PTR dwContext)
  2565. {
  2566. if (dwReason == CSCPROC_REASON_BEGIN) {
  2567. return CSCPROC_RETURN_CONTINUE;
  2568. } else if (dwReason == CSCPROC_REASON_MORE_DATA) {
  2569. MyPrintf(L"%ws\r\n", (lpszFullPath != NULL) ? lpszFullPath : L"None");
  2570. return CSCPROC_RETURN_CONTINUE;
  2571. }
  2572. //
  2573. // CSC_PROC_END
  2574. //
  2575. if (dwParam2 == ERROR_SUCCESS) {
  2576. MyPrintf(L"Succeeded\r\n");
  2577. } else {
  2578. MyPrintf(L"Error=%d \r\n", dwParam2);
  2579. }
  2580. return CSCPROC_RETURN_CONTINUE;
  2581. }
  2582. DWORD
  2583. MyEnumForStatsProcW(
  2584. LPCWSTR lpszFullPath,
  2585. DWORD dwStatus,
  2586. DWORD dwHintFlags,
  2587. DWORD dwPinCount,
  2588. WIN32_FIND_DATAW *lpFind32,
  2589. DWORD dwReason,
  2590. DWORD dwParam1,
  2591. DWORD dwParam2,
  2592. DWORD_PTR dwContext)
  2593. {
  2594. if (dwReason == CSCPROC_REASON_BEGIN) {
  2595. MyPrintf(L"(1)%ws ", (lpszFullPath != NULL) ? lpszFullPath : L"None");
  2596. if (lpFind32 != NULL)
  2597. MyPrintf(L"[%ws]\r\n", lpFind32->cFileName);
  2598. MyPrintf(L" Status=0x%02x HintFlags=0x%02x "
  2599. L"Pincount=%3d Reason=0x%x Param1=0x%x Param2=0x%x\r\n",
  2600. dwStatus,
  2601. dwHintFlags,
  2602. dwPinCount,
  2603. dwReason,
  2604. dwParam1,
  2605. dwParam2);
  2606. return CSCPROC_RETURN_CONTINUE;
  2607. } else if (dwReason == CSCPROC_REASON_MORE_DATA) {
  2608. MyPrintf(L"(2)%ws ", (lpszFullPath != NULL) ? lpszFullPath : L"None");
  2609. if (lpFind32 != NULL)
  2610. MyPrintf(L" %ws\r\n", lpFind32->cFileName);
  2611. MyPrintf(L" Status=0x%02x HintFlags=0x%02x "
  2612. L"Pincount=%3d Reason=0x%x Param1=0x%x Param2=0x%x\r\n",
  2613. dwStatus,
  2614. dwHintFlags,
  2615. dwPinCount,
  2616. dwReason,
  2617. dwParam1,
  2618. dwParam2);
  2619. return CSCPROC_RETURN_CONTINUE;
  2620. }
  2621. //
  2622. // CSC_PROC_END
  2623. //
  2624. MyPrintf(L"(3)%ws\r\n", (lpszFullPath != NULL) ? lpszFullPath : L"None");
  2625. if (dwParam2 == ERROR_SUCCESS) {
  2626. MyPrintf(L"Succeeded\r\n");
  2627. } else {
  2628. MyPrintf(L"Error=%d \r\n", dwParam2);
  2629. }
  2630. return CSCPROC_RETURN_CONTINUE;
  2631. }
  2632. struct {
  2633. DWORD ShareStatus;
  2634. LPWSTR ShareStatusName;
  2635. } ShareStatusStuff[] = {
  2636. { FLAG_CSC_SHARE_STATUS_MODIFIED_OFFLINE, L"MODIFIED_OFFLINE " },
  2637. { FLAG_CSC_SHARE_STATUS_CONNECTED, L"CONNECTED " },
  2638. { FLAG_CSC_SHARE_STATUS_FILES_OPEN, L"FILES_OPEN " },
  2639. { FLAG_CSC_SHARE_STATUS_FINDS_IN_PROGRESS, L"FINDS_IN_PROGRESS " },
  2640. { FLAG_CSC_SHARE_STATUS_DISCONNECTED_OP, L"DISCONNECTED_OP " },
  2641. { FLAG_CSC_SHARE_MERGING, L"MERGING " },
  2642. { 0, NULL }
  2643. };
  2644. DWORD
  2645. ShareStatusToEnglish(
  2646. DWORD Status,
  2647. LPWSTR OutputBuffer)
  2648. {
  2649. ULONG i;
  2650. OutputBuffer[0] = L'\0';
  2651. for (i = 0; ShareStatusStuff[i].ShareStatusName; i++) {
  2652. if (Status & ShareStatusStuff[i].ShareStatus)
  2653. wcscat(OutputBuffer, ShareStatusStuff[i].ShareStatusName);
  2654. }
  2655. if ((Status & FLAG_CSC_SHARE_STATUS_CACHING_MASK) == FLAG_CSC_SHARE_STATUS_MANUAL_REINT)
  2656. wcscat(OutputBuffer, L"MANUAL_REINT ");
  2657. else if ((Status & FLAG_CSC_SHARE_STATUS_CACHING_MASK) == FLAG_CSC_SHARE_STATUS_AUTO_REINT)
  2658. wcscat(OutputBuffer, L"AUTO_REINT ");
  2659. else if ((Status & FLAG_CSC_SHARE_STATUS_CACHING_MASK) == FLAG_CSC_SHARE_STATUS_VDO)
  2660. wcscat(OutputBuffer, L"VDO ");
  2661. else if ((Status & FLAG_CSC_SHARE_STATUS_CACHING_MASK) == FLAG_CSC_SHARE_STATUS_NO_CACHING)
  2662. wcscat(OutputBuffer, L"NO_CACHING ");
  2663. return 0;
  2664. }
  2665. struct {
  2666. DWORD FileStatus;
  2667. LPWSTR FileStatusName;
  2668. } FileStatusStuff[] = {
  2669. { FLAG_CSC_COPY_STATUS_DATA_LOCALLY_MODIFIED, L"DATA_LOCALLY_MODIFIED " },
  2670. { FLAG_CSC_COPY_STATUS_ATTRIB_LOCALLY_MODIFIED, L"ATTRIB_LOCALLY_MODIFIED " },
  2671. { FLAG_CSC_COPY_STATUS_TIME_LOCALLY_MODIFIED, L"TIME_LOCALLY_MODIFIED " },
  2672. { FLAG_CSC_COPY_STATUS_STALE, L"STALE " },
  2673. { FLAG_CSC_COPY_STATUS_LOCALLY_DELETED, L"LOCALLY_DELETED " },
  2674. { FLAG_CSC_COPY_STATUS_SPARSE, L"SPARSE " },
  2675. { FLAG_CSC_COPY_STATUS_ORPHAN, L"ORPHAN " },
  2676. { FLAG_CSC_COPY_STATUS_SUSPECT, L"SUSPECT " },
  2677. { FLAG_CSC_COPY_STATUS_LOCALLY_CREATED, L"LOCALLY_CREATED " },
  2678. { 0x00010000, L"USER_READ " },
  2679. { 0x00020000, L"USER_WRITE " },
  2680. { 0x00040000, L"GUEST_READ " },
  2681. { 0x00080000, L"GUEST_WRITE " },
  2682. { 0x00100000, L"OTHER_READ " },
  2683. { 0x00200000, L"OTHER_WRITE " },
  2684. { FLAG_CSC_COPY_STATUS_IS_FILE, L"IS_FILE " },
  2685. { FLAG_CSC_COPY_STATUS_FILE_IN_USE, L"FILE_IN_USE " },
  2686. { 0, NULL }
  2687. };
  2688. DWORD
  2689. FileStatusToEnglish(
  2690. DWORD Status,
  2691. LPWSTR OutputBuffer)
  2692. {
  2693. ULONG i;
  2694. OutputBuffer[0] = L'\0';
  2695. for (i = 0; FileStatusStuff[i].FileStatusName; i++) {
  2696. if (Status & FileStatusStuff[i].FileStatus)
  2697. wcscat(OutputBuffer, FileStatusStuff[i].FileStatusName);
  2698. }
  2699. return 0;
  2700. }
  2701. struct {
  2702. DWORD HintFlag;
  2703. LPWSTR HintName;
  2704. } HintStuff[] = {
  2705. { FLAG_CSC_HINT_PIN_USER, L"PIN_USER " },
  2706. { FLAG_CSC_HINT_PIN_INHERIT_USER, L"PIN_INHERIT_USER " },
  2707. { FLAG_CSC_HINT_PIN_INHERIT_SYSTEM, L"PIN_INHERIT_SYSTEM " },
  2708. { FLAG_CSC_HINT_CONSERVE_BANDWIDTH, L"CONSERVE_BANDWIDTH " },
  2709. { FLAG_CSC_HINT_PIN_SYSTEM, L"PIN_SYSTEM " },
  2710. { 0, NULL }
  2711. };
  2712. DWORD
  2713. HintsToEnglish(
  2714. DWORD Hint,
  2715. LPWSTR OutputBuffer)
  2716. {
  2717. ULONG i;
  2718. OutputBuffer[0] = L'\0';
  2719. for (i = 0; HintStuff[i].HintName; i++) {
  2720. if (Hint & HintStuff[i].HintFlag)
  2721. wcscat(OutputBuffer, HintStuff[i].HintName);
  2722. }
  2723. return 0;
  2724. }
  2725. BOOLEAN
  2726. LooksToBeAShare(LPWSTR Name)
  2727. {
  2728. //
  2729. // See if we have \\server\share or \\server\share\<something>
  2730. // Assume a valid name passed in...
  2731. //
  2732. ULONG Len = wcslen(Name);
  2733. ULONG i;
  2734. ULONG SlashCount = 0;
  2735. // Remove any trailing '\'s
  2736. while (Len >= 1) {
  2737. if (Name[Len-1] == L'\\') {
  2738. Name[Len-1] = L'\0';
  2739. Len--;
  2740. } else {
  2741. break;
  2742. }
  2743. }
  2744. for (i = 0; Name[i]; i++) {
  2745. if (Name[i] == L'\\')
  2746. SlashCount++;
  2747. }
  2748. if (SlashCount > 3)
  2749. return FALSE;
  2750. return TRUE;
  2751. }
  2752. DWORD
  2753. CmdDisconnect(
  2754. PWSTR DisconnectArg)
  2755. {
  2756. HSHADOW hDir;
  2757. SHADOWINFO sSI;
  2758. BOOL bResult;
  2759. HANDLE hDBShadow = INVALID_HANDLE_VALUE;
  2760. ULONG junk;
  2761. ULONG Status = 0;
  2762. ULONG hShare;
  2763. PWCHAR wCp;
  2764. ULONG SlashCount = 0;
  2765. if (fSwDebug == TRUE)
  2766. MyPrintf(L"CmdDisconnect(%ws)\r\n", DisconnectArg);
  2767. GetFileAttributes(DisconnectArg);
  2768. Status = GetLastError();
  2769. if (Status != NO_ERROR)
  2770. goto AllDone;
  2771. SlashCount = 0;
  2772. for (wCp = DisconnectArg; *wCp; wCp++) {
  2773. if (*wCp == L'\\')
  2774. SlashCount++;
  2775. if (SlashCount == 3) {
  2776. *wCp = L'\0';
  2777. break;
  2778. }
  2779. }
  2780. hDBShadow = CreateFile(
  2781. L"\\\\.\\shadow",
  2782. FILE_EXECUTE,
  2783. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2784. NULL,
  2785. OPEN_EXISTING,
  2786. 0,
  2787. NULL);
  2788. if (hDBShadow == INVALID_HANDLE_VALUE) {
  2789. MyPrintf(L"CmdDisconnect:Failed open of shadow device\r\n");
  2790. Status = GetLastError();
  2791. goto AllDone;
  2792. }
  2793. memset(&sSI, 0, sizeof(SHADOWINFO));
  2794. sSI.cbBufferSize = (wcslen(DisconnectArg)+1) * sizeof(WCHAR);
  2795. sSI.lpBuffer = DisconnectArg;
  2796. bResult = DeviceIoControl(
  2797. hDBShadow, // device
  2798. IOCTL_TAKE_SERVER_OFFLINE, // control code
  2799. (LPVOID)&sSI, // in buffer
  2800. 0, // inbuffer size
  2801. NULL, // out buffer
  2802. 0, // out buffer size
  2803. &junk, // bytes returned
  2804. NULL); // overlapped
  2805. if (!bResult) {
  2806. MyPrintf(L"CmdDisconnect:DeviceIoControl IOCTL_TAKE_SERVER_OFFLINE failed\n");
  2807. Status = GetLastError();
  2808. goto AllDone;
  2809. }
  2810. AllDone:
  2811. if (fSwDebug == TRUE)
  2812. MyPrintf(L"CmdDisconnect exit %d\r\n", Status);
  2813. if (hDBShadow != INVALID_HANDLE_VALUE)
  2814. CloseHandle(hDBShadow);
  2815. return Status;
  2816. }
  2817. DWORD
  2818. CmdGetShadow(
  2819. PWSTR GetShadowArg)
  2820. {
  2821. DWORD Status = 0;
  2822. DWORD dwErr = ERROR_SUCCESS;
  2823. HANDLE hDBShadow = INVALID_HANDLE_VALUE;
  2824. HSHADOW hShadow = 0;
  2825. HSHADOW hDir = 0;
  2826. WIN32_FIND_DATAW sFind32 = {0};
  2827. SHADOWINFO sSI = {0};
  2828. PWCHAR wCp = NULL;
  2829. BOOL bResult = FALSE;
  2830. DWORD junk;
  2831. WCHAR TimeBuf1[40];
  2832. WCHAR TimeBuf2[40];
  2833. WCHAR TimeBuf3[40];
  2834. if (fSwDebug == TRUE)
  2835. MyPrintf(L"CmdGetShadow(%ws)\r\n", GetShadowArg);
  2836. if (GetShadowArg == NULL) {
  2837. dwErr = ERROR_INVALID_PARAMETER;
  2838. goto AllDone;
  2839. }
  2840. swscanf(GetShadowArg, L"%x:", &hDir);
  2841. for (wCp = GetShadowArg; *wCp && *wCp != L':'; wCp++)
  2842. ;
  2843. if (*wCp != L':') {
  2844. dwErr = ERROR_INVALID_PARAMETER;
  2845. goto AllDone;
  2846. }
  2847. wCp++;
  2848. if (wcslen(wCp) >= MAX_PATH) {
  2849. dwErr = ERROR_INVALID_PARAMETER;
  2850. goto AllDone;
  2851. }
  2852. wcscpy(sFind32.cFileName, wCp);
  2853. if (fSwDebug == TRUE)
  2854. MyPrintf(L"hDir=0x%x cFileName=[%ws]\r\n", hDir, sFind32.cFileName);
  2855. hDBShadow = CreateFile(
  2856. L"\\\\.\\shadow",
  2857. GENERIC_READ | GENERIC_WRITE,
  2858. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2859. NULL,
  2860. OPEN_EXISTING,
  2861. 0,
  2862. NULL);
  2863. if (hDBShadow == INVALID_HANDLE_VALUE) {
  2864. MyPrintf(L"CmdGetShadow:Failed open of shadow device\r\n");
  2865. dwErr = GetLastError();
  2866. goto AllDone;
  2867. }
  2868. sSI.hDir = hDir;
  2869. sSI.lpFind32 = &sFind32;
  2870. bResult = DeviceIoControl(
  2871. hDBShadow, // device
  2872. IOCTL_GETSHADOW, // control code
  2873. (LPVOID)&sSI, // in buffer
  2874. 0, // inbuffer size
  2875. NULL, // out buffer
  2876. 0, // out buffer size
  2877. &junk, // bytes returned
  2878. NULL); // overlapped
  2879. if (!bResult) {
  2880. MyPrintf(L"CmdGetShadow:DeviceIoControl IOCTL_GETSHADOW failed\n");
  2881. dwErr = GetLastError();
  2882. goto AllDone;
  2883. }
  2884. ConvertGmtTimeToString(sFind32.ftCreationTime, TimeBuf1);
  2885. ConvertGmtTimeToString(sFind32.ftLastAccessTime, TimeBuf2);
  2886. ConvertGmtTimeToString(sFind32.ftLastWriteTime, TimeBuf3);
  2887. MyPrintf(L"\r\n");
  2888. MyPrintf(L"%ws:\r\n"
  2889. L" Size=0x%x:0x%x Attr=0x%x\r\n"
  2890. L" CreationTime: %ws\r\n"
  2891. L" LastAccessTime: %ws\r\n"
  2892. L" LastWriteTime: %ws\r\n",
  2893. sFind32.cFileName,
  2894. sFind32.nFileSizeHigh,
  2895. sFind32.nFileSizeLow,
  2896. sFind32.dwFileAttributes,
  2897. TimeBuf1,
  2898. TimeBuf2,
  2899. TimeBuf3);
  2900. MyPrintf(L" hShare=0x%x hDir=0x%x hShadow=0x%x Status=0x%x HintFlags=0x%x\r\n",
  2901. sSI.hShare,
  2902. sSI.hDir,
  2903. sSI.hShadow,
  2904. sSI.uStatus,
  2905. sSI.ulHintFlags);
  2906. MyPrintf(L"\r\n");
  2907. AllDone:
  2908. if (fSwDebug == TRUE)
  2909. MyPrintf(L"CmdGetShadowArg exit %d\r\n", Status);
  2910. if (hDBShadow != INVALID_HANDLE_VALUE)
  2911. CloseHandle(hDBShadow);
  2912. return dwErr;
  2913. }
  2914. DWORD
  2915. CmdGetShadowInfo(
  2916. PWSTR GetShadowInfoArg)
  2917. {
  2918. DWORD Status = 0;
  2919. DWORD dwErr = ERROR_SUCCESS;
  2920. HANDLE hDBShadow = INVALID_HANDLE_VALUE;
  2921. HSHADOW hShadow = 0;
  2922. HSHADOW hDir = 0;
  2923. WIN32_FIND_DATAW sFind32 = {0};
  2924. SHADOWINFO sSI = {0};
  2925. BOOL bResult = FALSE;
  2926. DWORD junk;
  2927. WCHAR TimeBuf1[40];
  2928. WCHAR TimeBuf2[40];
  2929. WCHAR TimeBuf3[40];
  2930. if (fSwDebug == TRUE)
  2931. MyPrintf(L"CmdGetShadowInfo(%ws)\r\n", GetShadowInfoArg);
  2932. if (GetShadowInfoArg == NULL) {
  2933. dwErr = ERROR_INVALID_PARAMETER;
  2934. goto AllDone;
  2935. }
  2936. swscanf(GetShadowInfoArg, L"%x:%x", &hDir, &hShadow);
  2937. if (fSwDebug == TRUE)
  2938. MyPrintf(L"hDir=0x%x hShadow=0x%x\r\n", hDir, hShadow);
  2939. hDBShadow = CreateFile(
  2940. L"\\\\.\\shadow",
  2941. GENERIC_READ | GENERIC_WRITE,
  2942. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2943. NULL,
  2944. OPEN_EXISTING,
  2945. 0,
  2946. NULL);
  2947. if (hDBShadow == INVALID_HANDLE_VALUE) {
  2948. MyPrintf(L"CmdGetShadowInfo:Failed open of shadow device\r\n");
  2949. dwErr = GetLastError();
  2950. goto AllDone;
  2951. }
  2952. sSI.hDir = hDir;
  2953. sSI.hShadow = hShadow;
  2954. sSI.lpFind32 = &sFind32;
  2955. bResult = DeviceIoControl(
  2956. hDBShadow, // device
  2957. IOCTL_SHADOW_GET_SHADOW_INFO, // control code
  2958. (LPVOID)&sSI, // in buffer
  2959. 0, // inbuffer size
  2960. NULL, // out buffer
  2961. 0, // out buffer size
  2962. &junk, // bytes returned
  2963. NULL); // overlapped
  2964. if (!bResult) {
  2965. MyPrintf(L"CmdGetShadowInfo:DeviceIoControl IOCTL_SHADOW_GET_SHADOW_INFO failed\n");
  2966. dwErr = GetLastError();
  2967. goto AllDone;
  2968. }
  2969. ConvertGmtTimeToString(sFind32.ftCreationTime, TimeBuf1);
  2970. ConvertGmtTimeToString(sFind32.ftLastAccessTime, TimeBuf2);
  2971. ConvertGmtTimeToString(sFind32.ftLastWriteTime, TimeBuf3);
  2972. MyPrintf(L"\r\n");
  2973. MyPrintf(L"%ws:\r\n"
  2974. L" Size=0x%x:0x%x Attr=0x%x\r\n"
  2975. L" CreationTime: %ws\r\n"
  2976. L" LastAccessTime: %ws\r\n"
  2977. L" LastWriteTime: %ws\r\n",
  2978. sFind32.cFileName,
  2979. sFind32.nFileSizeHigh,
  2980. sFind32.nFileSizeLow,
  2981. sFind32.dwFileAttributes,
  2982. TimeBuf1,
  2983. TimeBuf2,
  2984. TimeBuf3);
  2985. MyPrintf(L"\r\n");
  2986. AllDone:
  2987. if (fSwDebug == TRUE)
  2988. MyPrintf(L"CmdGetShadowInfoArg exit %d\r\n", Status);
  2989. if (hDBShadow != INVALID_HANDLE_VALUE)
  2990. CloseHandle(hDBShadow);
  2991. return dwErr;
  2992. }
  2993. DWORD
  2994. CmdShareId(
  2995. PWSTR ShareIdArg)
  2996. {
  2997. DWORD dwErr = ERROR_SUCCESS;
  2998. ULONG ShareId = 0;
  2999. BOOL fRet;
  3000. WCHAR Buffer[100];
  3001. ULONG BufSize = sizeof(Buffer);
  3002. HMODULE hmodCscDll = LoadLibrary(TEXT("cscdll.dll"));
  3003. CSCSHAREIDTOSHARENAME pCSCShareIdToShareName = NULL;
  3004. if (fSwDebug == TRUE)
  3005. MyPrintf(L"CmdShareId(%ws)\r\n", ShareIdArg);
  3006. if (ShareIdArg == NULL) {
  3007. dwErr = ERROR_INVALID_PARAMETER;
  3008. goto AllDone;
  3009. }
  3010. swscanf(ShareIdArg, L"%x", &ShareId);
  3011. if (fSwDebug == TRUE)
  3012. MyPrintf(L"ShareId=0x%x\r\n", ShareId);
  3013. if (hmodCscDll == NULL) {
  3014. dwErr = GetLastError();
  3015. goto AllDone;
  3016. }
  3017. pCSCShareIdToShareName = (CSCSHAREIDTOSHARENAME) GetProcAddress(
  3018. hmodCscDll,
  3019. "CSCShareIdToShareName");
  3020. if (pCSCShareIdToShareName == NULL) {
  3021. dwErr = GetLastError();
  3022. goto AllDone;
  3023. }
  3024. fRet = (pCSCShareIdToShareName)(ShareId, (PBYTE)Buffer, &BufSize);
  3025. if (fRet == FALSE) {
  3026. dwErr = GetLastError();
  3027. goto AllDone;
  3028. }
  3029. MyPrintf(L"ShareId 0x%x = %ws\r\n", ShareId, Buffer);
  3030. AllDone:
  3031. if (hmodCscDll != NULL)
  3032. FreeLibrary(hmodCscDll);
  3033. if (fSwDebug == TRUE)
  3034. MyPrintf(L"CmdShareIdToShareName exit %d\r\n", dwErr);
  3035. return dwErr;
  3036. }
  3037. DWORD
  3038. CmdExclusionList(
  3039. PWSTR ExclusionListArg)
  3040. {
  3041. HSHADOW hDir;
  3042. SHADOWINFO sSI;
  3043. BOOL bResult;
  3044. HANDLE hDBShadow = INVALID_HANDLE_VALUE;
  3045. ULONG junk;
  3046. ULONG Status = 0;
  3047. ULONG hShare;
  3048. if (fSwDebug == TRUE)
  3049. MyPrintf(L"CmdExclusionList(%ws)\r\n", ExclusionListArg);
  3050. if (ExclusionListArg == NULL) {
  3051. ExclusionListArg = vtzDefaultExclusionList;
  3052. }
  3053. MyPrintf(L"Setting exclusion list to \"%ws\"\r\n", ExclusionListArg);
  3054. hDBShadow = CreateFile(
  3055. L"\\\\.\\shadow",
  3056. GENERIC_READ | GENERIC_WRITE,
  3057. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3058. NULL,
  3059. OPEN_EXISTING,
  3060. 0,
  3061. NULL);
  3062. if (hDBShadow == INVALID_HANDLE_VALUE) {
  3063. MyPrintf(L"CmdExclusionList:Failed open of shadow device\r\n");
  3064. Status = GetLastError();
  3065. goto AllDone;
  3066. }
  3067. memset(&sSI, 0, sizeof(SHADOWINFO));
  3068. sSI.uSubOperation = SHADOW_SET_EXCLUSION_LIST;
  3069. sSI.lpBuffer = ExclusionListArg;
  3070. sSI.cbBufferSize = (wcslen(ExclusionListArg)+1) * sizeof(WCHAR);
  3071. bResult = DeviceIoControl(
  3072. hDBShadow, // device
  3073. IOCTL_DO_SHADOW_MAINTENANCE, // control code
  3074. (LPVOID)&sSI, // in buffer
  3075. 0, // inbuffer size
  3076. NULL, // out buffer
  3077. 0, // out buffer size
  3078. &junk, // bytes returned
  3079. NULL); // overlapped
  3080. AllDone:
  3081. if (fSwDebug == TRUE)
  3082. MyPrintf(L"CmdExclusionList exit %d\r\n", Status);
  3083. if (hDBShadow != INVALID_HANDLE_VALUE)
  3084. CloseHandle(hDBShadow);
  3085. return Status;
  3086. }
  3087. DWORD
  3088. CmdBWConservationList(
  3089. PWSTR BWConservationListArg)
  3090. {
  3091. HSHADOW hDir;
  3092. SHADOWINFO sSI;
  3093. BOOL bResult;
  3094. HANDLE hDBShadow = INVALID_HANDLE_VALUE;
  3095. ULONG junk;
  3096. ULONG Status = 0;
  3097. ULONG hShare;
  3098. if (fSwDebug == TRUE)
  3099. MyPrintf(L"CmdBWConservationList(%ws)\r\n", BWConservationListArg);
  3100. if (BWConservationListArg == NULL) {
  3101. BWConservationListArg = L" ";
  3102. }
  3103. MyPrintf(L"Setting BWConservation list to \"%ws\"\r\n", BWConservationListArg);
  3104. hDBShadow = CreateFile(
  3105. L"\\\\.\\shadow",
  3106. GENERIC_READ | GENERIC_WRITE,
  3107. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3108. NULL,
  3109. OPEN_EXISTING,
  3110. 0,
  3111. NULL);
  3112. if (hDBShadow == INVALID_HANDLE_VALUE) {
  3113. MyPrintf(L"CmdBWConservationList:Failed open of shadow device\r\n");
  3114. Status = GetLastError();
  3115. goto AllDone;
  3116. }
  3117. memset(&sSI, 0, sizeof(SHADOWINFO));
  3118. sSI.uSubOperation = SHADOW_SET_BW_CONSERVE_LIST;
  3119. sSI.lpBuffer = BWConservationListArg;
  3120. sSI.cbBufferSize = (wcslen(BWConservationListArg)+1) * sizeof(WCHAR);
  3121. bResult = DeviceIoControl(
  3122. hDBShadow, // device
  3123. IOCTL_DO_SHADOW_MAINTENANCE, // control code
  3124. (LPVOID)&sSI, // in buffer
  3125. 0, // inbuffer size
  3126. NULL, // out buffer
  3127. 0, // out buffer size
  3128. &junk, // bytes returned
  3129. NULL); // overlapped
  3130. AllDone:
  3131. if (fSwDebug == TRUE)
  3132. MyPrintf(L"CmdBWConservationList exit %d\r\n", Status);
  3133. if (hDBShadow != INVALID_HANDLE_VALUE)
  3134. CloseHandle(hDBShadow);
  3135. return Status;
  3136. }
  3137. DWORD
  3138. CmdDetector(
  3139. VOID)
  3140. {
  3141. HSHADOW hDir;
  3142. SHADOWINFO sSI;
  3143. BOOL bResult;
  3144. HANDLE hDBShadow = INVALID_HANDLE_VALUE;
  3145. ULONG junk;
  3146. ULONG Status = ERROR_SUCCESS;
  3147. ULONG hShare;
  3148. if (fSwDebug == TRUE)
  3149. MyPrintf(L"CmdDetector()\r\n");
  3150. hDBShadow = CreateFile(
  3151. L"\\\\.\\shadow",
  3152. GENERIC_READ | GENERIC_WRITE,
  3153. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3154. NULL,
  3155. OPEN_EXISTING,
  3156. 0,
  3157. NULL);
  3158. if (hDBShadow == INVALID_HANDLE_VALUE) {
  3159. MyPrintf(L"CmdDetector:Failed open of shadow device\r\n");
  3160. Status = GetLastError();
  3161. goto AllDone;
  3162. }
  3163. memset(&sSI, 0, sizeof(SHADOWINFO));
  3164. sSI.uSubOperation = SHADOW_SPARSE_STALE_DETECTION_COUNTER;
  3165. bResult = DeviceIoControl(
  3166. hDBShadow, // device
  3167. IOCTL_DO_SHADOW_MAINTENANCE, // control code
  3168. (LPVOID)&sSI, // in buffer
  3169. 0, // inbuffer size
  3170. NULL, // out buffer
  3171. 0, // out buffer size
  3172. &junk, // bytes returned
  3173. NULL); // overlapped
  3174. if (bResult)
  3175. MyPrintf(L"%d\r\n", sSI.dwError);
  3176. else
  3177. Status = sSI.dwError;
  3178. AllDone:
  3179. if (fSwDebug == TRUE)
  3180. MyPrintf(L"CmdDetector exit %d\r\n", Status);
  3181. if (hDBShadow != INVALID_HANDLE_VALUE)
  3182. CloseHandle(hDBShadow);
  3183. return Status;
  3184. }
  3185. DWORD
  3186. CmdSwitches(
  3187. VOID)
  3188. {
  3189. HSHADOW hDir;
  3190. SHADOWINFO sSI;
  3191. BOOL bResult;
  3192. HANDLE hDBShadow = INVALID_HANDLE_VALUE;
  3193. ULONG junk;
  3194. ULONG Status = ERROR_SUCCESS;
  3195. ULONG hShare;
  3196. if (fSwDebug == TRUE)
  3197. MyPrintf(L"CmdSwitches()\r\n");
  3198. hDBShadow = CreateFile(
  3199. L"\\\\.\\shadow",
  3200. GENERIC_READ | GENERIC_WRITE,
  3201. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3202. NULL,
  3203. OPEN_EXISTING,
  3204. 0,
  3205. NULL);
  3206. if (hDBShadow == INVALID_HANDLE_VALUE) {
  3207. MyPrintf(L"CmdSwitches:Failed open of shadow device\r\n");
  3208. Status = GetLastError();
  3209. goto AllDone;
  3210. }
  3211. memset(&sSI, 0, sizeof(SHADOWINFO));
  3212. sSI.uOp = SHADOW_SWITCH_GET_STATE;
  3213. bResult = DeviceIoControl(
  3214. hDBShadow, // device
  3215. IOCTL_SWITCHES, // control code
  3216. (LPVOID)&sSI, // in buffer
  3217. 0, // inbuffer size
  3218. NULL, // out buffer
  3219. 0, // out buffer size
  3220. &junk, // bytes returned
  3221. NULL); // overlapped
  3222. if (bResult) {
  3223. MyPrintf(L"0x%08x", sSI.uStatus);
  3224. if (sSI.uStatus != 0) {
  3225. MyPrintf(L" (");
  3226. if (sSI.uStatus & SHADOW_SWITCH_SHADOWING)
  3227. MyPrintf(L"SHADOW_SWITCH_SHADOWING ");
  3228. if (sSI.uStatus & SHADOW_SWITCH_LOGGING)
  3229. MyPrintf(L"SHADOW_SWITCH_LOGGING ");
  3230. if (sSI.uStatus & SHADOW_SWITCH_SPEAD_OPTIMIZE)
  3231. MyPrintf(L"SHADOW_SWITCH_SPEAD_OPTIMIZE ");
  3232. MyPrintf(L")");
  3233. }
  3234. if ((sSI.uStatus & SHADOW_SWITCH_SHADOWING) == 0)
  3235. MyPrintf(L" ... csc is disabled");
  3236. else
  3237. MyPrintf(L" ... csc is enabled");
  3238. MyPrintf(L"\r\n");
  3239. } else {
  3240. Status = sSI.dwError;
  3241. }
  3242. AllDone:
  3243. if (fSwDebug == TRUE)
  3244. MyPrintf(L"CmdSwitches exit %d\r\n", Status);
  3245. if (hDBShadow != INVALID_HANDLE_VALUE)
  3246. CloseHandle(hDBShadow);
  3247. return Status;
  3248. }
  3249. DWORD
  3250. CmdGetSpace(
  3251. VOID)
  3252. {
  3253. DWORD Error = ERROR_SUCCESS;
  3254. WCHAR szVolume[MAX_PATH];
  3255. LARGE_INTEGER MaxSpace;
  3256. LARGE_INTEGER CurrentSpace;
  3257. DWORD TotalFiles;
  3258. DWORD TotalDirs;
  3259. BOOL fRet;
  3260. if (fSwDebug == TRUE)
  3261. MyPrintf(L"CmdGetSpace()\r\n");
  3262. fRet = CSCGetSpaceUsageW(
  3263. szVolume,
  3264. sizeof(szVolume)/sizeof(WCHAR),
  3265. &MaxSpace.HighPart,
  3266. &MaxSpace.LowPart,
  3267. &CurrentSpace.HighPart,
  3268. &CurrentSpace.LowPart,
  3269. &TotalFiles,
  3270. &TotalDirs);
  3271. if (fRet == FALSE) {
  3272. Error = GetLastError();
  3273. goto AllDone;
  3274. }
  3275. MyPrintf(
  3276. L"Volume: %ws\r\n"
  3277. L"MaxSpace: 0x%x:0x%x (%d)\r\n"
  3278. L"CurrentSpace: 0x%x:0x%x (%d)\r\n"
  3279. L"TotalFiles: %d\r\n"
  3280. L"TotalDirs: %d\r\n",
  3281. szVolume,
  3282. MaxSpace.HighPart,
  3283. MaxSpace.LowPart,
  3284. MaxSpace.LowPart,
  3285. CurrentSpace.HighPart,
  3286. CurrentSpace.LowPart,
  3287. CurrentSpace.LowPart,
  3288. TotalFiles,
  3289. TotalDirs);
  3290. AllDone:
  3291. if (fSwDebug == TRUE)
  3292. MyPrintf(L"CmdGetSpace exit %d\r\n", Error);
  3293. return Error;
  3294. }
  3295. DWORD
  3296. CmdIsServerOffline(
  3297. PWSTR IsServerOfflineArg)
  3298. {
  3299. DWORD Error = ERROR_SUCCESS;
  3300. BOOL fRet;
  3301. BOOL fOffline = FALSE;
  3302. if (fSwDebug == TRUE)
  3303. MyPrintf(L"CmdIsServerOffline(%ws)\r\n", IsServerOfflineArg);
  3304. fRet = CSCIsServerOfflineW(
  3305. IsServerOfflineArg,
  3306. &fOffline);
  3307. if (fRet == FALSE) {
  3308. Error = GetLastError();
  3309. goto AllDone;
  3310. }
  3311. if (fOffline == TRUE)
  3312. MyPrintf(L"Offline\r\n");
  3313. else
  3314. MyPrintf(L"Online\r\n");
  3315. AllDone:
  3316. if (fSwDebug == TRUE)
  3317. MyPrintf(L"CmdIsServerOffline exit %d\r\n", Error);
  3318. return Error;
  3319. }
  3320. DWORD
  3321. CmdSetShareStatus(
  3322. PWSTR SetShareStatusArg)
  3323. {
  3324. HSHADOW hDir;
  3325. SHADOWINFO sSI;
  3326. BOOL bResult;
  3327. HANDLE hDBShadow = INVALID_HANDLE_VALUE;
  3328. ULONG junk;
  3329. ULONG Status = 0;
  3330. ULONG StatusToSet = 0;
  3331. ULONG hShare = 0;
  3332. if (fSwDebug == TRUE)
  3333. MyPrintf(L"CmdSetShareStatus(%ws)\r\n", SetShareStatusArg);
  3334. if (fSwSet == TRUE && fSwClear == TRUE) {
  3335. MyPrintf(L"Can't have both SET and CLEAR\r\n");
  3336. Status = ERROR_INVALID_PARAMETER;
  3337. goto AllDone;
  3338. }
  3339. hDBShadow = CreateFile(
  3340. L"\\\\.\\shadow",
  3341. GENERIC_READ | GENERIC_WRITE,
  3342. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3343. NULL,
  3344. OPEN_EXISTING,
  3345. 0,
  3346. NULL);
  3347. if (hDBShadow == INVALID_HANDLE_VALUE) {
  3348. MyPrintf(L"CmdSetShareStatus:Failed open of shadow device\r\n");
  3349. Status = GetLastError();
  3350. goto AllDone;
  3351. }
  3352. swscanf(SetShareStatusArg, L"%x:%x", &hShare, &StatusToSet);
  3353. if (fSwDebug == TRUE)
  3354. MyPrintf(L"CmdSetShareStatus hShare=0x%x StatusToSet=0x%x\r\n", hShare, StatusToSet);
  3355. memset(&sSI, 0, sizeof(SHADOWINFO));
  3356. sSI.hShare = hShare;
  3357. if (fSwSet == TRUE) {
  3358. sSI.uStatus = StatusToSet;
  3359. sSI.uOp = SHADOW_FLAGS_OR;
  3360. } else if (fSwClear == TRUE) {
  3361. sSI.uStatus = ~StatusToSet;
  3362. sSI.uOp = SHADOW_FLAGS_AND;
  3363. } else {
  3364. MyPrintf(L"Missing /SET or /CLEAR\r\n");
  3365. Status = ERROR_INVALID_PARAMETER;
  3366. goto AllDone;
  3367. }
  3368. bResult = DeviceIoControl(
  3369. hDBShadow, // device
  3370. IOCTL_SET_SHARE_STATUS, // control code
  3371. (LPVOID)&sSI, // in buffer
  3372. 0, // inbuffer size
  3373. NULL, // out buffer
  3374. 0, // out buffer size
  3375. &junk, // bytes returned
  3376. NULL); // overlapped
  3377. if (!bResult) {
  3378. MyPrintf(L"CmdSetShareStatus:DeviceIoControl IOCTL_SET_SHARE_STATUS failed\n");
  3379. Status = GetLastError();
  3380. goto AllDone;
  3381. }
  3382. AllDone:
  3383. if (fSwDebug == TRUE)
  3384. MyPrintf(L"CmdSetShareStatus exit %d\r\n", Status);
  3385. if (hDBShadow != INVALID_HANDLE_VALUE)
  3386. CloseHandle(hDBShadow);
  3387. return Status;
  3388. }
  3389. #define MAX_OFFSETS 256
  3390. #define PAGESIZE 4096
  3391. ULONG OffsetArgs[MAX_OFFSETS];
  3392. DWORD
  3393. CmdRandW(
  3394. PWSTR CmdRandWArg)
  3395. {
  3396. DWORD dwError = ERROR_SUCCESS;
  3397. DWORD dwFileSize;
  3398. DWORD dwOffset;
  3399. DWORD dwOffsetHigh;
  3400. UCHAR uchData;
  3401. HANDLE hFile = INVALID_HANDLE_VALUE;
  3402. ULONG i;
  3403. LONG WriteCount = 0;
  3404. LONG PageCount = 0;
  3405. PBYTE wArray = NULL;
  3406. if (fSwDebug == TRUE) {
  3407. MyPrintf(L"CmdRandW(%ws)\r\n", CmdRandWArg);
  3408. if (fArgOffset == TRUE)
  3409. MyPrintf(L" OFFSET [%ws]\r\n", pwszOffsetArg);
  3410. }
  3411. srand( (unsigned)time( NULL ) );
  3412. hFile = CreateFileW(
  3413. CmdRandWArg, // name
  3414. GENERIC_READ|GENERIC_WRITE, // access mode
  3415. FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
  3416. NULL, // security descriptor
  3417. OPEN_EXISTING, // create disposition
  3418. 0, // file statributes if created
  3419. NULL); // template handle
  3420. if (hFile == INVALID_HANDLE_VALUE) {
  3421. dwError = GetLastError();
  3422. goto AllDone;
  3423. }
  3424. dwFileSize = GetFileSize(hFile, NULL);
  3425. MyPrintf(L"File size = %d bytes\r\n", dwFileSize);
  3426. if (fArgOffset == TRUE) {
  3427. WriteCount = CountOffsetArgs(pwszOffsetArg, OffsetArgs);
  3428. if (WriteCount == 0) {
  3429. MyPrintf(L"No offsets specified, or - nothing to do.\r\n");
  3430. goto AllDone;
  3431. } else if (WriteCount < 0) {
  3432. MyPrintf(L"Error in offset list. Exiting.\r\n");
  3433. dwError = ERROR_INVALID_PARAMETER;
  3434. goto AllDone;
  3435. }
  3436. } else {
  3437. PageCount = (dwFileSize / PAGESIZE);
  3438. WriteCount = rand() % PageCount;
  3439. }
  3440. if (fSwDebug == TRUE) {
  3441. wArray = calloc(1, PageCount * sizeof(BYTE));
  3442. MyPrintf(L"There are %d pages in the file\r\n", PageCount);
  3443. }
  3444. if (dwFileSize == -1) {
  3445. dwError = GetLastError();
  3446. if (fSwDebug == TRUE)
  3447. MyPrintf(L"GetFileSize() failed %d\r\n", dwError);
  3448. goto AllDone;
  3449. }
  3450. if (dwFileSize == 0) {
  3451. MyPrintf(L"0 sized file - nothing to do.\r\n");
  3452. goto AllDone;
  3453. }
  3454. MyPrintf(L"Writing %d times\r\n", WriteCount);
  3455. for (i = 0; i < (ULONG)WriteCount; ++i) {
  3456. DWORD dwReturn;
  3457. if (fArgOffset == TRUE)
  3458. dwOffset = OffsetArgs[i];
  3459. else
  3460. dwOffset = ((rand() % PageCount) * PAGESIZE) + (rand() % PAGESIZE);
  3461. uchData = (UCHAR)rand();
  3462. if (SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
  3463. dwError = GetLastError();
  3464. if (fSwDebug == TRUE)
  3465. MyPrintf(L"SetFilePointer() failed %d\r\n", dwError);
  3466. goto AllDone;
  3467. }
  3468. MyPrintf(L"writing 0x02%x Page %d offset %d (offset %d(0x%x))\r\n", uchData,
  3469. dwOffset / PAGESIZE,
  3470. dwOffset % PAGESIZE,
  3471. dwOffset,
  3472. dwOffset);
  3473. if (wArray)
  3474. wArray[dwOffset/PAGESIZE]++;
  3475. if (!WriteFile(hFile, &uchData, 1, &dwReturn, NULL)) {
  3476. dwError = GetLastError();
  3477. if (fSwDebug == TRUE)
  3478. MyPrintf(L"WriteFile() failed %d\r\n", dwError);
  3479. goto AllDone;
  3480. }
  3481. }
  3482. if (wArray) {
  3483. for (i = 0; i < (ULONG)PageCount; i++) {
  3484. MyPrintf(L"%d", wArray[i]);
  3485. if ((i % 50) == 0)
  3486. MyPrintf(L"\r\n");
  3487. }
  3488. MyPrintf(L"\r\n");
  3489. }
  3490. // If EOF is specified, truncate the file to a random length
  3491. if (fSwEof == TRUE) {
  3492. ULONG xx = rand() % 5;
  3493. ULONG NewLen = (rand() * rand()) % (dwFileSize * 2);
  3494. if (xx == 0 || xx == 1) {
  3495. MyPrintf(L"New EOF = %d\r\n", NewLen);
  3496. SetFilePointer(hFile, NewLen, 0, FILE_BEGIN);
  3497. SetEndOfFile(hFile);
  3498. } else {
  3499. MyPrintf(L"No EOF change.\r\n");
  3500. }
  3501. }
  3502. AllDone:
  3503. if (hFile != INVALID_HANDLE_VALUE)
  3504. CloseHandle(hFile);
  3505. if (wArray)
  3506. free(wArray);
  3507. if (fSwDebug == TRUE)
  3508. MyPrintf(L"CmdRandW exit %d\r\n", dwError);
  3509. return dwError;
  3510. }
  3511. LONG
  3512. CountOffsetArgs(
  3513. PWSTR OffsetArg,
  3514. ULONG OffsetArray[])
  3515. {
  3516. // Expect a string of the form "N,N,N,N" where each N can be hex OR decimal.
  3517. // Store results in OffsetArray[]
  3518. // Limit is MAX_OFFSETS offsets, to make things easy.
  3519. ULONG i;
  3520. PWCHAR wCp = OffsetArg;
  3521. PWCHAR wNum = NULL;
  3522. ULONG iRet;
  3523. for (i = 0; i < MAX_OFFSETS; i++) {
  3524. if (*wCp == L'\0')
  3525. break;
  3526. wNum = wCp;
  3527. while (*wCp != L',' && *wCp != L'\0')
  3528. wCp++;
  3529. if (*wCp == L',')
  3530. *wCp++ = L'\0';
  3531. iRet = swscanf(wNum, L"%Li", &OffsetArray[i]);
  3532. if (iRet <= 0)
  3533. return -1;
  3534. }
  3535. if (fSwDebug == TRUE) {
  3536. ULONG j;
  3537. for (j = 0; j < i; j++)
  3538. MyPrintf(L"[%d]-0x%x(%d)\r\n", j, OffsetArray[j], OffsetArray[j]);
  3539. MyPrintf(L"CountOffsetArgs returning %d\r\n", i);
  3540. }
  3541. return i;
  3542. }
  3543. #if defined(CSCUTIL_INTERNAL)
  3544. DWORD
  3545. CmdBitcopy(
  3546. PWSTR BitcopyArg)
  3547. {
  3548. DWORD Error = ERROR_FILE_NOT_FOUND;
  3549. LPWSTR lpszTempName = NULL;
  3550. if (!CSCCopyReplicaW(BitcopyArg, &lpszTempName)) {
  3551. Error = GetLastError();
  3552. } else {
  3553. Error = ERROR_SUCCESS;
  3554. }
  3555. if (Error == ERROR_SUCCESS) {
  3556. Error = DumpBitMap(lpszTempName);
  3557. DeleteFile(lpszTempName);
  3558. }
  3559. return Error;
  3560. }
  3561. #endif // CSCUTIL_INTERNAL