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.

272 lines
5.9 KiB

  1. /*
  2. This program cleans build.exe trees.
  3. */
  4. #ifndef BUILD_STABILIZE_EXPORTS
  5. #include "windows.h"
  6. #define NUMBER_OF(x) (sizeof(x)/sizeof((x)[0]))
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. // error messages
  11. const static wchar_t errorNT[] = L"This program requires Windows NT.\n";
  12. #define NumberOf(x) (sizeof(x)/sizeof((x)[0]))
  13. void Log(const char* s, const wchar_t* q)
  14. {
  15. printf(s, q);
  16. }
  17. void Log(const wchar_t* s)
  18. {
  19. printf("%ls\n", s);
  20. }
  21. void Fail(const wchar_t* s)
  22. {
  23. Log(s);
  24. exit(EXIT_FAILURE);
  25. }
  26. void LogRecurse(const wchar_t* s)
  27. {
  28. printf("Recurse %ls\n", s);
  29. }
  30. void LogDelete(const wchar_t* s)
  31. {
  32. printf("Delete %ls\n", s);
  33. }
  34. bool IsDotOrDotDot(const wchar_t* s)
  35. {
  36. return
  37. (
  38. s[0] == '.' &&
  39. (
  40. (s[1] == 0)
  41. || (s[1] == '.' && s[2] == 0)
  42. )
  43. );
  44. }
  45. #endif /* BUILD_STABILIZE_EXPORTS */
  46. #ifdef BUILD_STABILIZE_EXPORTS
  47. #define LogRecurse(x) /* nothing */
  48. #define LogDelete(x) /* nothing */
  49. #define wchar_t char
  50. #define WIN32_FIND_DATAW WIN32_FIND_DATAA
  51. #define FindFirstFileW FindFirstFileA
  52. #define wcscpy strcpy
  53. #define DeleteFileW DeleteFileA
  54. #define RemoveDirectoryW RemoveDirectoryA
  55. #define wcslen strlen
  56. #define FindNextFileW FindNextFileA
  57. #endif /* BUILD_STABILIZE_EXPORTS */
  58. void DeleteDirectory(wchar_t* directory, int length, WIN32_FIND_DATAW* wfd)
  59. {
  60. directory[length] = 0;
  61. LogRecurse(directory);
  62. directory[length] = '\\';
  63. directory[length+1] = '*';
  64. directory[length+2] = 0;
  65. HANDLE hFind = FindFirstFileW(directory, wfd);
  66. if (hFind != INVALID_HANDLE_VALUE)
  67. {
  68. __try
  69. {
  70. do
  71. {
  72. if (IsDotOrDotDot(wfd->cFileName))
  73. {
  74. continue;
  75. }
  76. DWORD dwFileAttributes = wfd->dwFileAttributes;
  77. directory[length] = '\\';
  78. wcscpy(directory + length + 1, wfd->cFileName);
  79. if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  80. {
  81. DeleteDirectory(directory, length + 1 + wcslen(wfd->cFileName), wfd);
  82. }
  83. else
  84. {
  85. if (dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY))
  86. {
  87. //if (!SetFileAttributesW(directory, dwFileAttributes & ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY)))
  88. {
  89. // ...
  90. }
  91. }
  92. if (DeleteFileW(directory))
  93. {
  94. LogDelete(directory);
  95. }
  96. else
  97. {
  98. // ...
  99. }
  100. }
  101. } while (FindNextFileW(hFind, wfd));
  102. }
  103. __finally
  104. {
  105. FindClose(hFind);
  106. }
  107. }
  108. directory[length] = 0;
  109. RemoveDirectoryW(directory);
  110. LogDelete(directory);
  111. }
  112. #ifndef BUILD_STABILIZE_EXPORTS
  113. void CleanDirectory(
  114. const wchar_t* obj,
  115. wchar_t* directory,
  116. int length,
  117. WIN32_FIND_DATAW* wfd
  118. )
  119. {
  120. directory[length] = 0;
  121. LogRecurse(directory);
  122. // clean build[d,fre,chk].[log,wrn,err] builds
  123. const static wchar_t dfrechk[][4] = { L"", L"d", L"fre", L"chk" };
  124. const static wchar_t logwrnerr[][4] = { L"log", L"wrn", L"err" };
  125. for (int b = 0 ; b < NUMBER_OF(dfrechk); b++)
  126. {
  127. for (int g = 0 ; g < NUMBER_OF(logwrnerr) ; ++g)
  128. {
  129. swprintf(directory + length, L"\\build%s.%s", dfrechk[b], logwrnerr[g]);
  130. if (DeleteFileW(directory))
  131. {
  132. LogDelete(directory);
  133. }
  134. else
  135. {
  136. // ...
  137. }
  138. }
  139. }
  140. // Dangerous to clean files out of source directory, but:
  141. // FUTURE clean *.plg (VC Project Log?) files
  142. // FUTURE clean *.rsp files that sometimes appear in source dir?
  143. // FUTURE clean MSG*.bin files that sometimes appear in source dir?
  144. // FUTURE clean RC* files that sometimes appear in source dir?
  145. directory[length] = '\\';
  146. wcscpy(directory + length + 1, obj);
  147. HANDLE hFind = FindFirstFileW(directory, wfd);
  148. if (hFind != INVALID_HANDLE_VALUE)
  149. {
  150. __try
  151. {
  152. do
  153. {
  154. directory[length] = '\\';
  155. wcscpy(directory + length + 1, wfd->cFileName);
  156. DeleteDirectory(directory, length + 1 + wcslen(wfd->cFileName), wfd);
  157. }
  158. while (FindNextFileW(hFind, wfd));
  159. }
  160. __finally
  161. {
  162. FindClose(hFind);
  163. }
  164. }
  165. directory[length] = '\\';
  166. directory[length+1] = '*';
  167. directory[length+2] = 0;
  168. hFind = FindFirstFileW(directory, wfd);
  169. if (hFind != INVALID_HANDLE_VALUE)
  170. {
  171. __try
  172. {
  173. do
  174. {
  175. if (IsDotOrDotDot(wfd->cFileName))
  176. {
  177. continue;
  178. }
  179. if (!(wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  180. {
  181. continue;
  182. }
  183. directory[length] = '\\';
  184. wcscpy(directory + length + 1, wfd->cFileName);
  185. CleanDirectory(obj, directory, length + 1 + wcslen(wfd->cFileName), wfd);
  186. } while (FindNextFileW(hFind, wfd));
  187. }
  188. __finally
  189. {
  190. FindClose(hFind);
  191. }
  192. }
  193. directory[length] = 0;
  194. }
  195. #define Lx(x) L ## x
  196. #define L(x) Lx(x)
  197. int Clean(
  198. int argc,
  199. wchar_t** argv
  200. )
  201. {
  202. Log(L"Clean version " L(__TIME__) L" " L(__DATE__));
  203. // are we running on NT?
  204. long version = GetVersion();
  205. int build = ((version >> 16) & 0x7fff);
  206. int majorVersion = (version & 0xff);
  207. bool nt = !(version & 0x80000000);
  208. if (!nt)
  209. {
  210. Fail(errorNT);
  211. }
  212. // These two buffers are shared by the whole call tree. Be careful.
  213. WIN32_FIND_DATAW wfd;
  214. wchar_t currentDirectory[1U << 15];
  215. if (argc != 2)
  216. {
  217. Log(
  218. "Usage: %ls [delete string].\n"
  219. " Typical deletion strings are obj, objd, and obj?.\n"
  220. " This will recursively delete directories matching\n"
  221. " the deletion string. It will also delete\n"
  222. " all files named build[d,fre,chk].[log,wrn,err].\n",
  223. argv[0] ? argv[0] : L"xxx.exe"
  224. );
  225. return EXIT_FAILURE;
  226. }
  227. // I prefer GetCurrentDirectory, but other programs just print '.'
  228. // if (!GetCurrentDirectoryW(NUMBER_OF(currentDirectory), currentDirectory))
  229. // {
  230. // Fail();
  231. // }
  232. currentDirectory[0] = '.';
  233. currentDirectory[1] = 0;
  234. CleanDirectory(argv[1], currentDirectory, wcslen(currentDirectory), &wfd);
  235. return EXIT_SUCCESS;
  236. }
  237. int __cdecl wmain(
  238. int argc,
  239. wchar_t** argv
  240. )
  241. {
  242. return Clean(argc, argv);
  243. }
  244. #endif /* BUILD_STABILIZE_EXPORTS */