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.

508 lines
11 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. collapse.c
  5. Abstract:
  6. Takes the formatting spaces out of an INF
  7. Author:
  8. Jim Schmidt (jimschm) 08-Jun-1999
  9. Revision History:
  10. <full name> (<alias>) <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. HANDLE g_hHeap;
  14. HINSTANCE g_hInst;
  15. BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID);
  16. BOOL
  17. pCallEntryPoints (
  18. DWORD Reason
  19. )
  20. {
  21. HINSTANCE Instance;
  22. //
  23. // Simulate DllMain
  24. //
  25. Instance = g_hInst;
  26. //
  27. // Initialize the common libs
  28. //
  29. if (!MigUtil_Entry (Instance, Reason, NULL)) {
  30. return FALSE;
  31. }
  32. return TRUE;
  33. }
  34. BOOL
  35. Init (
  36. VOID
  37. )
  38. {
  39. g_hHeap = GetProcessHeap();
  40. g_hInst = GetModuleHandle (NULL);
  41. return pCallEntryPoints (DLL_PROCESS_ATTACH);
  42. }
  43. VOID
  44. Terminate (
  45. VOID
  46. )
  47. {
  48. pCallEntryPoints (DLL_PROCESS_DETACH);
  49. }
  50. VOID
  51. HelpAndExit (
  52. VOID
  53. )
  54. {
  55. //
  56. // This routine is called whenever command line args are wrong
  57. //
  58. _ftprintf (
  59. stderr,
  60. TEXT("Command Line Syntax:\n\n")
  61. TEXT(" collapse <file> [output]\n")
  62. TEXT("\nDescription:\n\n")
  63. TEXT(" collapse takes the spaces out of an INF\n")
  64. TEXT("\nArguments:\n\n")
  65. TEXT(" file Specifies the input file name.\n")
  66. TEXT(" output Specifies the output file name. If not specified,\n")
  67. TEXT(" the original file is updated in place.\n")
  68. );
  69. exit (1);
  70. }
  71. #define MAX_BLOCK_SIZE 65536
  72. INT
  73. __cdecl
  74. _tmain (
  75. INT argc,
  76. PCTSTR argv[]
  77. )
  78. {
  79. INT i;
  80. PCTSTR OutputArg = NULL;
  81. PCTSTR FileArg = NULL;
  82. HANDLE Src, Dest;
  83. BOOL QuoteMode;
  84. BYTE InBuffer[MAX_BLOCK_SIZE];
  85. BYTE OutBuffer[MAX_BLOCK_SIZE];
  86. BOOL Unicode;
  87. TCHAR TempPath[MAX_TCHAR_PATH];
  88. TCHAR TempFile[MAX_TCHAR_PATH];
  89. DWORD Attribs;
  90. BOOL b;
  91. DWORD BytesRead;
  92. DWORD BytesWritten;
  93. PCSTR AnsiPtr, AnsiEnd;
  94. PCWSTR UnicodePtr, UnicodeEnd;
  95. PSTR AnsiOutPtr;
  96. PWSTR UnicodeOutPtr;
  97. PBYTE End;
  98. WORD LastChar;
  99. UINT Line;
  100. BOOL Comments;
  101. for (i = 1 ; i < argc ; i++) {
  102. if (argv[i][0] == TEXT('/') || argv[i][0] == TEXT('-')) {
  103. HelpAndExit();
  104. } else {
  105. if (OutputArg) {
  106. HelpAndExit();
  107. } else if (FileArg) {
  108. OutputArg = argv[i];
  109. } else {
  110. FileArg = argv[i];
  111. }
  112. }
  113. }
  114. //
  115. // Validate args
  116. //
  117. if (!FileArg) {
  118. HelpAndExit();
  119. }
  120. //
  121. // Begin processing
  122. //
  123. if (!Init()) {
  124. return 0;
  125. }
  126. if (!OutputArg) {
  127. OutputArg = FileArg;
  128. }
  129. GetTempPath (ARRAYSIZE(TempPath), TempPath);
  130. GetTempFileName (TempPath, TEXT("u2a"), 0, TempFile);
  131. Src = CreateFile (
  132. FileArg,
  133. GENERIC_READ,
  134. FILE_SHARE_READ,
  135. NULL,
  136. OPEN_EXISTING,
  137. FILE_ATTRIBUTE_NORMAL,
  138. NULL
  139. );
  140. if (Src != INVALID_HANDLE_VALUE) {
  141. b = TRUE;
  142. Attribs = GetFileAttributes (FileArg);
  143. Dest = CreateFile (
  144. TempFile,
  145. GENERIC_WRITE,
  146. 0,
  147. NULL,
  148. CREATE_ALWAYS,
  149. FILE_ATTRIBUTE_NORMAL,
  150. NULL
  151. );
  152. if (Dest == INVALID_HANDLE_VALUE) {
  153. b = FALSE;
  154. }
  155. } else {
  156. _tprintf (TEXT("Can't open %s for read permission.\n"), FileArg);
  157. b = FALSE;
  158. }
  159. if (b) {
  160. //
  161. // Src and Dest are valid now. Determine if Src is unicode.
  162. //
  163. b = ReadFile (Src, InBuffer, 2, &BytesRead, NULL);
  164. if (b && BytesRead == 2) {
  165. if (InBuffer[0] != 0xFF || InBuffer[1] != 0xFE) {
  166. SetFilePointer (Src, 0, NULL, FILE_BEGIN);
  167. Unicode = FALSE;
  168. } else {
  169. Unicode = TRUE;
  170. }
  171. }
  172. }
  173. if (b) {
  174. //
  175. // Do the conversion
  176. //
  177. LastChar = 0;
  178. QuoteMode = FALSE;
  179. Line = 1;
  180. Comments = FALSE;
  181. do {
  182. b = ReadFile (Src, InBuffer, ARRAYSIZE(InBuffer), &BytesRead, NULL);
  183. if (!b) {
  184. _tprintf (TEXT("Can't read from %s, error=%u\n"), Src, GetLastError());
  185. break;
  186. }
  187. if (!BytesRead) {
  188. //
  189. // Done
  190. //
  191. break;
  192. }
  193. if (!Unicode) {
  194. AnsiPtr = (PCSTR) InBuffer;
  195. AnsiEnd = (PCSTR) (InBuffer + BytesRead);
  196. AnsiOutPtr = (PSTR) OutBuffer;
  197. while (AnsiPtr < AnsiEnd) {
  198. if (*AnsiPtr == ';') {
  199. Comments = TRUE;
  200. }
  201. if (*AnsiPtr == '\r' || *AnsiPtr == '\n') {
  202. if (LastChar != '\r' && QuoteMode) {
  203. _tprintf (TEXT("Unmatched quotes found at line %u\n"), Line);
  204. }
  205. QuoteMode = FALSE;
  206. Comments = FALSE;
  207. if (LastChar != '\r' || *AnsiPtr != '\n') {
  208. Line++;
  209. }
  210. LastChar = (WORD) (*AnsiPtr);
  211. *AnsiOutPtr++ = *AnsiPtr;
  212. } else if (!Comments) {
  213. if (LastChar == '\r' || LastChar == '\n') {
  214. if (*AnsiPtr == '@') {
  215. LastChar = (WORD) (*AnsiPtr);
  216. } else {
  217. LastChar = 0;
  218. }
  219. } else if (LastChar == '@') {
  220. if (*AnsiPtr == '*') {
  221. LastChar = (WORD) (*AnsiPtr);
  222. } else {
  223. LastChar = 0;
  224. }
  225. } else if (LastChar == '*') {
  226. if (*AnsiPtr == ':') {
  227. Comments = TRUE;
  228. }
  229. LastChar = 0;
  230. } else {
  231. LastChar = 0;
  232. }
  233. if (Comments) {
  234. *AnsiOutPtr++ = *AnsiPtr;
  235. } else {
  236. if (*AnsiPtr == '\"') {
  237. QuoteMode = !QuoteMode;
  238. *AnsiOutPtr++ = *AnsiPtr;
  239. }
  240. else if (QuoteMode || *AnsiPtr != ' ') {
  241. *AnsiOutPtr++ = *AnsiPtr;
  242. }
  243. }
  244. } else {
  245. *AnsiOutPtr++ = *AnsiPtr;
  246. }
  247. AnsiPtr++;
  248. }
  249. End = (PBYTE) AnsiOutPtr;
  250. } else {
  251. UnicodePtr = (PCWSTR) InBuffer;
  252. UnicodeEnd = (PCWSTR) (InBuffer + BytesRead);
  253. UnicodeOutPtr = (PWSTR) OutBuffer;
  254. while (UnicodePtr < UnicodeEnd) {
  255. if (*UnicodePtr == L';') {
  256. Comments = TRUE;
  257. }
  258. if (*UnicodePtr == L'\r' || *UnicodePtr == L'\n') {
  259. if (LastChar != L'\r' && QuoteMode) {
  260. _tprintf (TEXT("Unmatched quotes found at line %u\n"), Line);
  261. }
  262. QuoteMode = FALSE;
  263. Comments = FALSE;
  264. if (LastChar != L'\r' || *UnicodePtr != L'\n') {
  265. Line++;
  266. }
  267. LastChar = (WORD) (*UnicodePtr);
  268. *UnicodeOutPtr++ = *UnicodePtr;
  269. } else if (!Comments) {
  270. if (LastChar == L'\r' || LastChar == L'\n') {
  271. if (*UnicodePtr == L'@') {
  272. LastChar = (WORD) (*UnicodePtr);
  273. } else {
  274. LastChar = 0;
  275. }
  276. } else if (LastChar == L'@') {
  277. if (*UnicodePtr == L'*') {
  278. LastChar = (WORD) (*UnicodePtr);
  279. } else {
  280. LastChar = 0;
  281. }
  282. } else if (LastChar == L'*') {
  283. if (*UnicodePtr == L':') {
  284. Comments = TRUE;
  285. }
  286. LastChar = 0;
  287. } else {
  288. LastChar = 0;
  289. }
  290. if (Comments) {
  291. *UnicodeOutPtr++ = *UnicodePtr;
  292. } else {
  293. if (*UnicodePtr == L'\"') {
  294. QuoteMode = !QuoteMode;
  295. *UnicodeOutPtr++ = *UnicodePtr;
  296. }
  297. else if (QuoteMode || *UnicodePtr != L' ') {
  298. *UnicodeOutPtr++ = *UnicodePtr;
  299. }
  300. }
  301. } else {
  302. *UnicodeOutPtr++ = *UnicodePtr;
  303. }
  304. UnicodePtr++;
  305. }
  306. End = (PBYTE) UnicodeOutPtr;
  307. }
  308. //
  309. // Now write the output
  310. //
  311. if (End > OutBuffer) {
  312. b = WriteFile (
  313. Dest,
  314. OutBuffer,
  315. End - OutBuffer,
  316. &BytesWritten,
  317. NULL
  318. );
  319. if (!b) {
  320. _tprintf (TEXT("Can't write to %s, error=%u\n"), TempFile, GetLastError());
  321. }
  322. }
  323. } while (b);
  324. }
  325. //
  326. // If success, rename the temp file to the output file
  327. //
  328. if (b) {
  329. CloseHandle (Src);
  330. CloseHandle (Dest);
  331. Src = INVALID_HANDLE_VALUE;
  332. Dest = INVALID_HANDLE_VALUE;
  333. SetFileAttributes (OutputArg, FILE_ATTRIBUTE_NORMAL);
  334. b = MoveFileEx (
  335. TempFile,
  336. OutputArg,
  337. MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING
  338. );
  339. if (!b) {
  340. _tprintf (TEXT("Can't move %s to %s, error=%u\n"), TempFile, OutputArg, GetLastError());
  341. } else {
  342. SetFileAttributes (OutputArg, Attribs);
  343. }
  344. }
  345. //
  346. // Cleanup
  347. //
  348. if (Src != INVALID_HANDLE_VALUE) {
  349. CloseHandle (Src);
  350. }
  351. if (Dest != INVALID_HANDLE_VALUE) {
  352. CloseHandle (Dest);
  353. }
  354. if (!b) {
  355. DeleteFile (Dest);
  356. } else {
  357. if (!StringIMatch (FileArg, OutputArg)) {
  358. _tprintf (TEXT("Collapse of %s to %s was successful\n"), FileArg, OutputArg);
  359. } else {
  360. _tprintf (TEXT("Collapse of %s was successful\n"), FileArg);
  361. }
  362. }
  363. //
  364. // End of processing
  365. //
  366. Terminate();
  367. return 0;
  368. }