Windows NT 4.0 source code leak
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.

273 lines
8.7 KiB

4 years ago
  1. /*** RM.C - a generalized remove and unremove mechanism ***********************
  2. *
  3. * Copyright (c) 1987-1990, Microsoft Corporation. All rights reserved.
  4. *
  5. * Purpose:
  6. * The three tools EXP, RM and UNDEL are used to delete files so
  7. * that they can be undeleted. This is done my renaming the file into
  8. * a hidden directory called DELETED.
  9. *
  10. * Notes:
  11. * All deleted files are kept in the directory .\deleted with a unique name.
  12. * The names are then kept in .\deleted\index.
  13. * deleted name (RM_RECLEN bytes).
  14. * The rm command will rename to the appropriate directory and make an entry.
  15. * the undelete command will rename back if there is a single item otherwise
  16. * it will give a list of alternatives. The exp command will free all deleted
  17. * objects.
  18. *
  19. * Revision History:
  20. * 07-Feb-1990 bw Add 'void' to walk() definition
  21. * 08-Jan-1990 SB SLM version upgrading added; Add CopyRightYrs Macro
  22. * 03-Jan-1990 SB define QH_TOPIC_NOT_FOUND
  23. * 21-Dec-1989 SB Changes for new index file format
  24. * 20-Dec-1989 SB Add check for return code of 3 for qh
  25. * 14-Dec-1989 LN Update Copyright to include 1990
  26. * 23-Oct-1989 LN Version no bumped to 1.01
  27. * 12-Oct-1989 LN Changed Usage message
  28. * 02-Oct-1989 LN Changed Version no to 1.00
  29. * 08-Aug-1989 BW Add Version number and update copyright.
  30. * 15-May-1987 WB Add /help
  31. * 22-Apr-1987 DL Add /k
  32. * 06-Apr-1987 BW Add copyright notice to usage.
  33. * 30-Mar-1990 BW Get help on RM.EXE, not EXP.EXE
  34. * 17-Oct-1990 w-barry Temporarily replaced 'rename' with 'rename_NT' until
  35. * DosMove is completely implemented on NT.
  36. *
  37. ******************************************************************************/
  38. /* I N C L U D E Files */
  39. #include <process.h>
  40. #include <string.h>
  41. /* Next two from ZTools */
  42. #include <stdio.h>
  43. #include <conio.h>
  44. #include <windows.h>
  45. #include <tools.h>
  46. /* D E F I N E s */
  47. #define CopyRightYrs "1987-90"
  48. /* Need 2 steps, first to get correct values in and 2nd to paste them */
  49. /* paste() is hacked to allow LEADING ZEROES */
  50. #define paste(a, b, c) #a ".0" #b ".00" #c
  51. #define VERSION(major, minor, buildno) paste(major, minor, buildno)
  52. #define QH_TOPIC_NOT_FOUND 3
  53. // BUGBUG 11-Sep-90 w-wilson Until console CRT is available in 32-bits
  54. //
  55. //#define cputs(s) fputs(s,stdout)
  56. //#define putch(c) putchar(c)
  57. //#define getch() getchar()
  58. //#define cprintf() printf()
  59. /* G L O B A L s */
  60. flagType fRecursive = FALSE; /* TRUE => descend tree */
  61. flagType fPrompt = FALSE; /* TRUE => query for removal */
  62. flagType fForce = FALSE; /* TRUE => no query for R/O files */
  63. flagType fKeepRO = FALSE; /* TRUE => keep R/O files */
  64. flagType fTakeOwnership = FALSE; /* TRUE => attempt takeown if fail */
  65. flagType fExpunge = FALSE; /* TRUE => expunge immediately */
  66. flagType fDelayUntilReboot = FALSE; /* TRUE => do delete next reboot */
  67. // Forward Function Declarations...
  68. void Usage( void );
  69. void walk( char *, struct findType *, void * );
  70. int _CRTAPI1 main( int, char ** );
  71. #if 0
  72. extern BOOL TakeOwnership( char *lpFileName );
  73. #endif /* 0 */
  74. void Usage()
  75. {
  76. printf(
  77. "Microsoft File Removal Utility. Version %s\n"
  78. "Copyright (C) Microsoft Corp %s. All rights reserved.\n\n"
  79. "Usage: RM [/help] [/ikft] [/x [/d]] [/r dir] files\n"
  80. " /help invoke Quick Help for this utility\n"
  81. " /i inquire of user for each file for permission to remove\n"
  82. " /k keep read only files, no prompting to remove them\n"
  83. " /r dir recurse into subdirectories\n"
  84. " /f force delete of read only files without prompting\n"
  85. " /t attempt to take ownership of file if delete fails\n"
  86. " /x dont save deleted files in deleted subdirectory\n"
  87. " /d delay until next reboot.\n",
  88. VERSION(rmj, rmm, rup), CopyRightYrs);
  89. exit(1);
  90. }
  91. void walk(p, b, dummy)
  92. char *p;
  93. struct findType *b;
  94. void * dummy;
  95. {
  96. char buf[MAX_PATH];
  97. int i, rc;
  98. if (strcmp(b->fbuf.cFileName, ".") && strcmp(b->fbuf.cFileName, "..") &&
  99. _strcmpi(b->fbuf.cFileName, "deleted")) {
  100. if (HASATTR(b->fbuf.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY)) {
  101. if (fRecursive) {
  102. switch (strend(p)[-1]) {
  103. case '/':
  104. case '\\':
  105. sprintf(buf, "%s*.*", p);
  106. break;
  107. default:
  108. sprintf(buf, "%s\\*.*", p);
  109. }
  110. forfile(buf, -1, walk, NULL);
  111. }
  112. }
  113. else if (fKeepRO && HASATTR(b->fbuf.dwFileAttributes, FILE_ATTRIBUTE_READONLY)) {
  114. printf("%s skipped\n", p);
  115. return;
  116. }
  117. else {
  118. if (fPrompt || (!fForce && HASATTR(b->fbuf.dwFileAttributes, FILE_ATTRIBUTE_READONLY))) {
  119. printf("%s? ", p);
  120. fflush(stdout);
  121. switch (_getch()) {
  122. case 'y':
  123. case 'Y':
  124. printf("Yes\n");
  125. break;
  126. case 'p':
  127. case 'P':
  128. printf("Proceeding without asking again\n");
  129. fPrompt = FALSE;
  130. break;
  131. default:
  132. printf(" skipped\n");
  133. return;
  134. }
  135. }
  136. fflush(stdout);
  137. if (HASATTR(b->fbuf.dwFileAttributes, FILE_ATTRIBUTE_READONLY))
  138. SetFileAttributes(p, b->fbuf.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
  139. for (i=0; i<2; i++) {
  140. if (fExpunge) {
  141. if (fDelayUntilReboot) {
  142. if (MoveFileEx(p, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)) {
  143. rc = 0;
  144. }
  145. else {
  146. rc = 1;
  147. }
  148. }
  149. else
  150. if (DeleteFile(p)) {
  151. rc = 0;
  152. }
  153. else {
  154. rc = 1;
  155. }
  156. }
  157. else {
  158. rc = fdelete(p);
  159. }
  160. #if 0
  161. if (rc == 0 || !fTakeOwnership) {
  162. break;
  163. }
  164. printf( "%s file not deleted - attempting to take ownership and try again.\n" );
  165. if (!TakeOwnership( p )) {
  166. printf( "%s file not deleted - unable to take ownership.\n" );
  167. rc = 0;
  168. break;
  169. }
  170. #else
  171. break;
  172. #endif /* 0 */
  173. }
  174. switch (rc) {
  175. case 0:
  176. break;
  177. case 1:
  178. printf("%s file does not exist\n" , p);
  179. break;
  180. case 2:
  181. printf("%s rename failed: %s\n", p, error());
  182. break;
  183. default:
  184. printf("%s internal error: %s\n", p, error());
  185. break;
  186. }
  187. }
  188. }
  189. dummy;
  190. }
  191. _CRTAPI1 main(c, v)
  192. int c;
  193. char *v[];
  194. {
  195. register char *p;
  196. int iRetCode;
  197. ConvertAppToOem( c, v );
  198. SHIFT(c,v);
  199. while (c && fSwitChr(*v[0])) {
  200. p = *v;
  201. while (*++p != '\0')
  202. switch (*p) {
  203. case 'f':
  204. fForce = TRUE;
  205. break;
  206. case 'i':
  207. fPrompt = TRUE;
  208. break;
  209. case 'k':
  210. fKeepRO = TRUE;
  211. break;
  212. case 'r':
  213. fRecursive = TRUE;
  214. break;
  215. case 't':
  216. fTakeOwnership = TRUE;
  217. break;
  218. case 'x':
  219. fExpunge = TRUE;
  220. break;
  221. case 'd':
  222. if (fExpunge) {
  223. fDelayUntilReboot = TRUE;
  224. break;
  225. }
  226. // Fall thru if /d without /x
  227. case 'h':
  228. if (!_strcmpi(p, "help")) {
  229. iRetCode = _spawnlp(P_WAIT, "qh.exe", "qh", "/u",
  230. "rm.exe", NULL);
  231. /* When qh returns QH_TOPIC_NOT_FOUND or when we
  232. * get -1 (returned when the spawn fails) then
  233. * give Usage() message
  234. */
  235. if (iRetCode != QH_TOPIC_NOT_FOUND && iRetCode != -1)
  236. exit(0);
  237. }
  238. /*
  239. * else fall thru...
  240. */
  241. default:
  242. Usage();
  243. }
  244. SHIFT(c,v);
  245. }
  246. while (c) {
  247. if (!forfile(*v, -1, walk, NULL)) {
  248. printf("%s does not exist\n", *v);
  249. }
  250. SHIFT(c,v);
  251. }
  252. return(0);
  253. }