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.

372 lines
9.0 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. icontool.c
  5. Abstract:
  6. Tool to extract icons from ICO, PE and NE files and to write them
  7. to an ICO or PE file
  8. Author:
  9. Calin Negreanu (calinn) 16 June 2000
  10. Revision History:
  11. <full name> (<alias>) <date> <comments>
  12. --*/
  13. #include "pch.h"
  14. HANDLE g_hHeap;
  15. HINSTANCE g_hInst;
  16. BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID);
  17. BOOL
  18. pCallEntryPoints (
  19. DWORD Reason
  20. )
  21. {
  22. switch (Reason) {
  23. case DLL_PROCESS_ATTACH:
  24. UtInitialize (NULL);
  25. FileEnumInitialize ();
  26. LogReInit (NULL, NULL, NULL, NULL);
  27. break;
  28. case DLL_PROCESS_DETACH:
  29. FileEnumTerminate ();
  30. UtTerminate ();
  31. break;
  32. }
  33. return TRUE;
  34. }
  35. BOOL
  36. Init (
  37. VOID
  38. )
  39. {
  40. g_hHeap = GetProcessHeap();
  41. g_hInst = GetModuleHandle (NULL);
  42. return pCallEntryPoints (DLL_PROCESS_ATTACH);
  43. }
  44. VOID
  45. Terminate (
  46. VOID
  47. )
  48. {
  49. pCallEntryPoints (DLL_PROCESS_DETACH);
  50. }
  51. VOID
  52. pHelpAndExit (
  53. VOID
  54. )
  55. {
  56. //
  57. // This routine is called whenever command line args are wrong
  58. //
  59. fprintf (
  60. stderr,
  61. "Command Line Syntax:\n\n"
  62. //
  63. // Describe command line syntax(es), indent 2 spaces
  64. //
  65. " icontool [/D:<destination file>] <node pattern> <leaf pattern>\n"
  66. "\nDescription:\n\n"
  67. //
  68. // Describe tool, indent 2 spaces
  69. //
  70. " Extracts icon groups from ICO, PE and NE files specified <node pattern> and\n"
  71. " <leaf pattern>. Optionally writes the extracted icons to either a PE file or\n"
  72. " a sequence of ICO files.\n"
  73. "\nArguments:\n\n"
  74. //
  75. // Describe args, indent 2 spaces, say optional if necessary
  76. //
  77. " /D:<destination file> - Specifies the destination file where all extracted icons\n"
  78. " are going to be written. It's either a PE file specification\n"
  79. " or a sequence of ICO files with %%d in name (like icon%%04d.ico)\n"
  80. " <node pattern> Specifies the directory pattern (like c:\\foo*\\bar?\\*)\n"
  81. " <leaf pattern> Specifies the file pattern (like abc*.exe)\n"
  82. );
  83. exit (1);
  84. }
  85. BOOL
  86. pGetFilePath (
  87. IN PCSTR UserSpecifiedFile,
  88. OUT PTSTR Buffer,
  89. IN UINT BufferTchars
  90. )
  91. {
  92. PSTR tempBuffer = NULL;
  93. CHAR modulePath[MAX_MBCHAR_PATH];
  94. CHAR currentDir[MAX_MBCHAR_PATH];
  95. PSTR p;
  96. PCSTR userFile = NULL;
  97. PSTR dontCare;
  98. __try {
  99. //
  100. // Locate the file using the full path specified by the user, or
  101. // if only a file spec was given, use the following priorities:
  102. //
  103. // 1. Current directory
  104. // 2. Directory where the tool is
  105. //
  106. // In all cases, return the full path to the file.
  107. //
  108. tempBuffer = AllocTextA (BufferTchars);
  109. *tempBuffer = 0;
  110. if (!_mbsrchr (UserSpecifiedFile, '\\')) {
  111. if (!GetModuleFileNameA (NULL, modulePath, ARRAYSIZE(modulePath))) {
  112. MYASSERT (FALSE);
  113. return FALSE;
  114. }
  115. p = _mbsrchr (modulePath, '\\');
  116. if (p) {
  117. *p = 0;
  118. } else {
  119. MYASSERT (FALSE);
  120. return FALSE;
  121. }
  122. if (!GetCurrentDirectoryA (ARRAYSIZE(currentDir), currentDir)) {
  123. MYASSERT (FALSE);
  124. return FALSE;
  125. }
  126. //
  127. // Let's see if it's in the current dir
  128. //
  129. userFile = JoinPathsA (currentDir, UserSpecifiedFile);
  130. if (DoesFileExistA (userFile)) {
  131. GetFullPathNameA (
  132. userFile,
  133. BufferTchars,
  134. tempBuffer,
  135. &dontCare
  136. );
  137. } else {
  138. //
  139. // Let's try the module dir
  140. //
  141. FreePathStringA (userFile);
  142. userFile = JoinPathsA (modulePath, UserSpecifiedFile);
  143. if (DoesFileExistA (userFile)) {
  144. GetFullPathNameA (
  145. userFile,
  146. BufferTchars,
  147. tempBuffer,
  148. &dontCare
  149. );
  150. }
  151. }
  152. } else {
  153. //
  154. // Use the full path that the user specified
  155. //
  156. GetFullPathNameA (
  157. UserSpecifiedFile,
  158. BufferTchars,
  159. tempBuffer,
  160. &dontCare
  161. );
  162. }
  163. //
  164. // Transfer output into caller's buffer. Note the TCHAR conversion.
  165. //
  166. #ifdef UNICODE
  167. KnownSizeAtoW (Buffer, tempBuffer);
  168. #else
  169. StringCopy (Buffer, tempBuffer);
  170. #endif
  171. }
  172. __finally {
  173. if (userFile) {
  174. FreePathStringA (userFile);
  175. }
  176. FreeTextA (tempBuffer);
  177. }
  178. return *Buffer != 0;
  179. }
  180. PCTSTR
  181. pGetIconFileType (
  182. IN DWORD FileType
  183. )
  184. {
  185. switch (FileType) {
  186. case ICON_ICOFILE:
  187. return TEXT("ICO File");
  188. case ICON_PEFILE:
  189. return TEXT("PE File");
  190. case ICON_NEFILE:
  191. return TEXT("NE File");
  192. }
  193. return TEXT("UNKNOWN ");
  194. }
  195. INT
  196. __cdecl
  197. _tmain (
  198. INT Argc,
  199. PCTSTR Argv[]
  200. )
  201. {
  202. INT i;
  203. PCTSTR nodePattern = NULL;
  204. PCTSTR leafPattern = NULL;
  205. PTSTR encodedPattern = NULL;
  206. PCSTR destFile = NULL;
  207. PSTR p;
  208. TCHAR destPath[MAX_PATH_PLUS_NUL];
  209. TCHAR destIcoPath[MAX_PATH_PLUS_NUL];
  210. FILETREE_ENUM e;
  211. ICON_ENUM iconEnum;
  212. PCSTR resourceId;
  213. DWORD totalIcons = 0;
  214. DWORD fileIcons = 0;
  215. DWORD fileType = 0;
  216. if (!Init()) {
  217. return 0;
  218. }
  219. for (i = 1 ; i < Argc ; i++) {
  220. if (Argv[i][0] == TEXT('/') || Argv[i][0] == TEXT('-')) {
  221. switch (_totlower (_tcsnextc (&Argv[i][1]))) {
  222. case TEXT('d'):
  223. if (Argv[i][2] == TEXT(':')) {
  224. destFile = &Argv[i][3];
  225. } else if (i + 1 < Argc) {
  226. i++;
  227. destFile = Argv[i];
  228. } else {
  229. pHelpAndExit();
  230. }
  231. if (!pGetFilePath (destFile, destPath, ARRAYSIZE(destPath))) {
  232. destPath [0] = 0;
  233. break;
  234. }
  235. break;
  236. default:
  237. pHelpAndExit();
  238. }
  239. } else {
  240. //
  241. // Parse other args that don't require / or -
  242. //
  243. if (nodePattern || leafPattern) {
  244. pHelpAndExit();
  245. }
  246. nodePattern = Argv[i];
  247. if (*nodePattern == TEXT('\"')) {
  248. nodePattern++;
  249. p = _tcsdec2 (nodePattern, GetEndOfString (nodePattern));
  250. if (p && *p == TEXT('\"')) {
  251. *p = 0;
  252. }
  253. }
  254. leafPattern = Argv[i+1];
  255. i++;
  256. }
  257. }
  258. if (!nodePattern) {
  259. pHelpAndExit ();
  260. }
  261. if (!leafPattern) {
  262. pHelpAndExit ();
  263. }
  264. //
  265. // Begin processing
  266. //
  267. encodedPattern = ObsBuildEncodedObjectStringEx (nodePattern, leafPattern, FALSE);
  268. if (EnumFirstFileInTree (&e, encodedPattern)) {
  269. // at this point, if we don't have a valid updateHandle and moduleHandle
  270. // we will assume that the destination specification is a sequence of ICO files.
  271. do {
  272. fileIcons = 0;
  273. if (IcoEnumFirstIconGroupInFile (e.NativeFullName, &iconEnum)) {
  274. fileType = iconEnum.FileType;
  275. do {
  276. if (destPath [0]) {
  277. if (fileIcons == 0x0b) {
  278. } else {
  279. if (!IcoWriteIconGroupToPeFile (destPath, iconEnum.IconGroup, &resourceId, NULL)) {
  280. wsprintf (destIcoPath, destPath, totalIcons);
  281. if (!IcoWriteIconGroupToIcoFile (destIcoPath, iconEnum.IconGroup, TRUE)) {
  282. printf ("Error writing icon group to destination file %s\n", destPath);
  283. }
  284. }
  285. }
  286. }
  287. totalIcons ++;
  288. fileIcons ++;
  289. } while (IcoEnumNextIconGroupInFile (&iconEnum));
  290. IcoAbortEnumIconGroup (&iconEnum);
  291. }
  292. if (fileIcons) {
  293. printf ("[%6u],[%6u] [%8s] %s\n", totalIcons, fileIcons, pGetIconFileType (fileType), e.NativeFullName);
  294. }
  295. } while (EnumNextFileInTree (&e));
  296. }
  297. //
  298. // End of processing
  299. //
  300. Terminate();
  301. return 0;
  302. }