Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

497 lines
9.5 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. dnnttree.c
  5. Abstract:
  6. Code for manipulating (removing) Windows NT directory trees
  7. for DOS-based setup.
  8. This code is highly dependent on the format of repair.inf.
  9. Author:
  10. Ted Miller (tedm) 30-March-1993
  11. Revision History:
  12. --*/
  13. #include "winnt.h"
  14. #include <string.h>
  15. #include <dos.h>
  16. #if 0 // /D removed
  17. //
  18. // /D is no longer supported
  19. //
  20. #define SETUP_LOG "setup.log"
  21. #define LINE_BUFFER_SIZE 750
  22. #define REPAIR_SECTION_NAME "Repair.WinntFiles"
  23. PCHAR RegistryFiles[] = { "system",
  24. "software",
  25. "default",
  26. "sam",
  27. "security",
  28. "userdef",
  29. NULL
  30. };
  31. PCHAR RegistrySuffixes[] = { "",".log",".alt",NULL };
  32. PCHAR
  33. DnpSectionName(
  34. IN PCHAR Line
  35. )
  36. /*++
  37. Routine Description:
  38. Determine whether a line is an inf section title, and return the
  39. section name if so.
  40. Arguments:
  41. Line - supplies line read from inf file.
  42. Return Value:
  43. NULL if line is not a section title. Otherwise, returns a buffer
  44. containing the name of the section, which the caller must free
  45. via FREE().
  46. --*/
  47. {
  48. PCHAR End;
  49. //
  50. // Skip leading whitespace.
  51. //
  52. Line += strspn(Line," \t");
  53. //
  54. // If first non-whitepsace char is not [, then this
  55. // is not a section name.
  56. //
  57. if(*Line != '[') {
  58. return(NULL);
  59. }
  60. //
  61. // Skip the left bracket.
  62. //
  63. Line++;
  64. //
  65. // Find the end of the section name. Look backwards for the terminating
  66. // right bracket.
  67. //
  68. if(End = strrchr(Line,']')) {
  69. *End = 0;
  70. }
  71. //
  72. // Duplicate the section name and return it to the caller.
  73. //
  74. return(DnDupString(Line));
  75. }
  76. PCHAR
  77. DnpFileToDelete(
  78. IN CHAR Drive,
  79. IN PCHAR Line
  80. )
  81. /*++
  82. Routine Description:
  83. Given a line from an inf file, pull out the second field on it and
  84. prefix this value with a drive spec. This forms a full pathname of
  85. a file contained within the windows nt installation being removed.
  86. Arguments:
  87. Drive - supplies drive letter of windows nt tree.
  88. Line - supplies line read from inf file.
  89. Return Value:
  90. NULL if line has no second field. Otherwise, returns a buffer
  91. containing the full pathname of the file, which the caller must free
  92. via FREE().
  93. --*/
  94. {
  95. BOOLEAN InQuote = FALSE;
  96. int Field = 0;
  97. PCHAR WS = " \t";
  98. PCHAR FieldStart;
  99. PCHAR FileToDelete;
  100. unsigned FieldLength;
  101. while(1) {
  102. if((Field == 1) && ((*Line == 0) || (!InQuote && (*Line == ',')))) {
  103. FieldLength = Line - FieldStart - 1;
  104. if(FileToDelete = MALLOC(FieldLength+3),FALSE) {
  105. FileToDelete[0] = Drive;
  106. FileToDelete[1] = ':';
  107. strncpy(FileToDelete+2,FieldStart+1,FieldLength);
  108. FileToDelete[FieldLength+2] = 0;
  109. }
  110. return(FileToDelete);
  111. }
  112. switch(*Line) {
  113. case 0:
  114. return(NULL);
  115. case '\"':
  116. InQuote = (BOOLEAN)!InQuote;
  117. break;
  118. case ',':
  119. if(!InQuote) {
  120. Field++;
  121. FieldStart = Line;
  122. }
  123. break;
  124. }
  125. Line++;
  126. }
  127. }
  128. VOID
  129. DnpDoDelete(
  130. IN PCHAR File
  131. )
  132. /*++
  133. Routine Description:
  134. Remove a single file from the windows nt installation,
  135. providing feedback to the user.
  136. If the file is in the system directory (as opposed to
  137. the system32 directory), then we will skip it. This is
  138. because the user might have installed into the win3.1
  139. directory, in which case some files in the system directory
  140. are shared between nt and 3.1 (like fonts!).
  141. Arguments:
  142. File - supplies full pathname of the file to be deleted.
  143. Return Value:
  144. None.
  145. --*/
  146. {
  147. struct find_t FindData;
  148. PCHAR p,q;
  149. p = DnDupString(File);
  150. strlwr(p);
  151. q = strstr(p,"\\system\\");
  152. FREE(p);
  153. if(q) {
  154. return;
  155. }
  156. DnWriteStatusText(DntRemovingFile,File);
  157. if(!_dos_findfirst(File,_A_RDONLY|_A_HIDDEN|_A_SYSTEM,&FindData)) {
  158. _dos_setfileattr(File,_A_NORMAL);
  159. remove(File);
  160. }
  161. }
  162. VOID
  163. DnpRemoveRegistryFiles(
  164. IN PCHAR NtRoot
  165. )
  166. /*++
  167. Routine Description:
  168. Remove a known list of registry files from a windows nt tree.
  169. Arguments:
  170. NtRoot - supplies the full path of the windows nt windows directory,
  171. such as d:\winnt.
  172. Return Value:
  173. None.
  174. --*/
  175. {
  176. unsigned f,s;
  177. CHAR RegistryFileName[256];
  178. for(f=0; RegistryFiles[f]; f++) {
  179. for(s=0; RegistrySuffixes[s]; s++) {
  180. sprintf(
  181. RegistryFileName,
  182. "%s\\system32\\config\\%s%s",
  183. NtRoot,
  184. RegistryFiles[f],
  185. RegistrySuffixes[s]
  186. );
  187. DnpDoDelete(RegistryFileName);
  188. }
  189. }
  190. }
  191. BOOLEAN
  192. DnpDoDeleteNtTree(
  193. IN PCHAR NtRoot
  194. )
  195. /*++
  196. Routine Description:
  197. Worker routine for removing the Windows NT system files listed in a
  198. setup.log file in a given windows nt root.
  199. Arguments:
  200. NtRoot - supplies the full path of the windows nt windows directory,
  201. such as d:\winnt.
  202. Return Value:
  203. TRUE if we got to the point of actually attempting to remove at least
  204. one file. FALSE otherwise.
  205. --*/
  206. {
  207. FILE *SetupLog;
  208. BOOLEAN FoundSection;
  209. PCHAR SetupLogName;
  210. PCHAR SectionName;
  211. PCHAR FileToDelete;
  212. CHAR LineBuffer[LINE_BUFFER_SIZE];
  213. BOOLEAN rc = FALSE;
  214. DnClearClientArea();
  215. DnDisplayScreen(&DnsRemovingNtFiles);
  216. DnWriteStatusText(NULL);
  217. //
  218. // Form the name of the setup log file.
  219. //
  220. SetupLogName = MALLOC(strlen(NtRoot)+sizeof(SETUP_LOG)+1,TRUE);
  221. strcpy(SetupLogName,NtRoot);
  222. strcat(SetupLogName,"\\" SETUP_LOG);
  223. //
  224. // Open the setup log file.
  225. //
  226. SetupLog = fopen(SetupLogName,"rt");
  227. if(SetupLog == NULL) {
  228. DnClearClientArea();
  229. DnDisplayScreen(&DnsCantOpenLogFile,SetupLogName);
  230. DnWriteStatusText(DntEnterEqualsContinue);
  231. while(DnGetKey() != ASCI_CR) ;
  232. goto xx1;
  233. }
  234. //
  235. // Read lines of the setup log file until we find the
  236. // section containing the list of files to be removed
  237. // ([Repair.WinntFiles]).
  238. //
  239. FoundSection = FALSE;
  240. while(!FoundSection && fgets(LineBuffer,LINE_BUFFER_SIZE,SetupLog)) {
  241. SectionName = DnpSectionName(LineBuffer);
  242. if(SectionName) {
  243. if(!stricmp(SectionName,REPAIR_SECTION_NAME)) {
  244. FoundSection = TRUE;
  245. }
  246. FREE(SectionName);
  247. }
  248. }
  249. if(FoundSection) {
  250. //
  251. // Read lines in this file until we encounter the end
  252. // of the file or the start of the next section.
  253. //
  254. while(fgets(LineBuffer,LINE_BUFFER_SIZE,SetupLog)) {
  255. //
  256. // If this line starts a new section, we're done.
  257. //
  258. if(SectionName = DnpSectionName(LineBuffer)) {
  259. FREE(SectionName);
  260. break;
  261. }
  262. //
  263. // Isolate the second field on the line; this is
  264. // the name of the file to delete.
  265. //
  266. if(FileToDelete = DnpFileToDelete(*NtRoot,LineBuffer)) {
  267. DnpDoDelete(FileToDelete);
  268. FREE(FileToDelete);
  269. rc = TRUE;
  270. }
  271. }
  272. } else {
  273. DnClearClientArea();
  274. DnWriteStatusText(DntEnterEqualsContinue);
  275. DnDisplayScreen(&DnsLogFileCorrupt,REPAIR_SECTION_NAME,SetupLogName);
  276. while(DnGetKey() != ASCI_CR) ;
  277. }
  278. fclose(SetupLog);
  279. xx1:
  280. FREE(SetupLogName);
  281. return(rc);
  282. }
  283. VOID
  284. DnDeleteNtTree(
  285. IN PCHAR NtRoot
  286. )
  287. /*++
  288. Routine Description:
  289. Worker routine for removing the Windows NT system files listed in a
  290. setup.log file in a given windows nt root.
  291. Arguments:
  292. NtRoot - supplies the full path of the windows nt windows directory,
  293. such as d:\winnt.
  294. Return Value:
  295. None.
  296. --*/
  297. {
  298. ULONG ValidKeys[] = { 0,0,ASCI_ESC,DN_KEY_F3,0 };
  299. ULONG Key;
  300. ValidKeys[0] = DniAccelRemove1;
  301. ValidKeys[1] = DniAccelRemove2;
  302. //
  303. // Get confirmation first.
  304. //
  305. DnClearClientArea();
  306. DnDisplayScreen(&DnsConfirmRemoveNt,NtRoot);
  307. DnWriteStatusText("%s %s",DntF3EqualsExit,DntXEqualsRemoveFiles);
  308. while(1) {
  309. Key = DnGetValidKey(ValidKeys);
  310. if((Key == DniAccelRemove1) || (Key == DniAccelRemove2)) {
  311. break;
  312. }
  313. if((Key == ASCI_ESC) || (Key == DN_KEY_F3)) {
  314. DnExit(1);
  315. }
  316. }
  317. if(DnpDoDeleteNtTree(NtRoot)) {
  318. DnpRemoveRegistryFiles(NtRoot);
  319. }
  320. }
  321. #endif // /D removed
  322. VOID
  323. DnRemovePagingFiles(
  324. VOID
  325. )
  326. /*++
  327. Routine Description:
  328. Remove Windows NT page files from root directory of drives we can see.
  329. Arguments:
  330. None.
  331. Return Value:
  332. None.
  333. --*/
  334. {
  335. CHAR Filename[16] = "?:\\pagefile.sys";
  336. int Drive;
  337. struct find_t FindData;
  338. DnClearClientArea();
  339. DnWriteStatusText(DntInspectingComputer);
  340. for(Filename[0]='A',Drive=1; Filename[0]<='Z'; Filename[0]++,Drive++) {
  341. if(DnIsDriveValid(Drive)
  342. && !DnIsDriveRemote(Drive,NULL)
  343. && !DnIsDriveRemovable(Drive)
  344. && !_dos_findfirst(Filename,_A_RDONLY|_A_SYSTEM|_A_HIDDEN, &FindData))
  345. {
  346. DnWriteStatusText(DntRemovingFile,Filename);
  347. remove(Filename);
  348. DnWriteStatusText(DntInspectingComputer);
  349. }
  350. }
  351. }