@@ -175,6 +175,100 @@ static LPWSTR fixup_commandline(LPWSTR exepath, LPWSTR *exep, int *wait,
175
175
176
176
#ifdef MAGIC_RESOURCE
177
177
178
+ #include <stdint.h>
179
+
180
+ #pragma pack(2)
181
+ struct resource_directory
182
+ {
183
+ int8_t width ;
184
+ int8_t height ;
185
+ int8_t color_count ;
186
+ int8_t reserved ;
187
+ int16_t planes ;
188
+ int16_t bit_count ;
189
+ int32_t bytes_in_resource ;
190
+ int16_t id ;
191
+ };
192
+
193
+ struct header
194
+ {
195
+ int16_t reserved ;
196
+ int16_t type ;
197
+ int16_t count ;
198
+ };
199
+
200
+ struct icon_header
201
+ {
202
+ int8_t width ;
203
+ int8_t height ;
204
+ int8_t color_count ;
205
+ int8_t reserved ;
206
+ int16_t planes ;
207
+ int16_t bit_count ;
208
+ int32_t bytes_in_resource ;
209
+ int32_t image_offset ;
210
+ };
211
+
212
+ struct icon_image
213
+ {
214
+ BITMAPINFOHEADER header ;
215
+ RGBQUAD colors ;
216
+ int8_t xors [1 ];
217
+ int8_t ands [1 ];
218
+ };
219
+
220
+ struct icon
221
+ {
222
+ int count ;
223
+ struct header * header ;
224
+ struct resource_directory * items ;
225
+ struct icon_image * * images ;
226
+ };
227
+
228
+ static int parse_ico_file (LPWSTR ico_path , struct icon * result )
229
+ {
230
+ struct header file_header ;
231
+ FILE * file = _wfopen (ico_path , L"rb" );
232
+ int i ;
233
+
234
+ if (!file ) {
235
+ fwprintf (stderr , L"could not open icon file '%s'" , ico_path );
236
+ return 1 ;
237
+ }
238
+
239
+ fread (& file_header , sizeof (struct header ), 1 , file );
240
+ result -> count = file_header .count ;
241
+
242
+ result -> header = malloc (sizeof (struct header ) + result -> count
243
+ * sizeof (struct resource_directory ));
244
+ result -> header -> reserved = 0 ;
245
+ result -> header -> type = 1 ;
246
+ result -> header -> count = result -> count ;
247
+ result -> items = (struct resource_directory * )(result -> header + 1 );
248
+ struct icon_header * icon_headers = malloc (result -> count
249
+ * sizeof (struct icon_header ));
250
+ fread (icon_headers , result -> count * sizeof (struct icon_header ),
251
+ 1 , file );
252
+ result -> images = malloc (result -> count * sizeof (struct icon_image * ));
253
+
254
+ for (i = 0 ; i < result -> count ; i ++ ) {
255
+ struct icon_image * * image = result -> images + i ;
256
+ struct icon_header * icon_header = icon_headers + i ;
257
+ struct resource_directory * item = result -> items + i ;
258
+
259
+ * image = malloc (icon_header -> bytes_in_resource );
260
+ fseek (file , icon_header -> image_offset , SEEK_SET );
261
+ fread (* image , icon_header -> bytes_in_resource , 1 , file );
262
+
263
+ memcpy (item , icon_header , sizeof (struct resource_directory ));
264
+ item -> id = (int16_t )(i + 1 );
265
+ }
266
+
267
+ fclose (file );
268
+
269
+ return 0 ;
270
+ }
271
+
178
272
static int wsuffixcmp (LPWSTR text , LPWSTR suffix )
179
273
{
180
274
int text_len = wcslen (text ), suffix_len = wcslen (suffix );
@@ -186,9 +280,10 @@ static int wsuffixcmp(LPWSTR text, LPWSTR suffix)
186
280
}
187
281
188
282
static int edit_resources (LPWSTR exe_path ,
189
- LPWSTR * commands , int command_count )
283
+ LPWSTR ico_path , LPWSTR * commands , int command_count )
190
284
{
191
285
WORD language = MAKELANGID (LANG_NEUTRAL , SUBLANG_DEFAULT );
286
+ struct icon icon ;
192
287
HANDLE handle ;
193
288
int i ;
194
289
@@ -206,13 +301,41 @@ static int edit_resources(LPWSTR exe_path,
206
301
return -1 ;
207
302
}
208
303
304
+ if (ico_path ) {
305
+ if (wsuffixcmp (ico_path , L".ico" )) {
306
+ fwprintf (stderr , L"Not an .ico file: '%s'" , ico_path );
307
+ return -1 ;
308
+ }
309
+ if (_waccess (ico_path , 0 ) == -1 ) {
310
+ fwprintf (stderr , L"File not found: '%s'" , ico_path );
311
+ return -1 ;
312
+ }
313
+
314
+ if (parse_ico_file (ico_path , & icon ))
315
+ return -1 ;
316
+ }
317
+
209
318
handle = BeginUpdateResource (exe_path , FALSE);
210
319
if (!handle ) {
211
320
fwprintf (stderr ,
212
321
L"Could not update resources of '%s'" , exe_path );
213
322
return -1 ;
214
323
}
215
324
325
+ if (ico_path ) {
326
+ int id = 1 ;
327
+ UpdateResource (handle , RT_GROUP_ICON ,
328
+ L"MAINICON" , language ,
329
+ icon .header , sizeof (struct header ) + icon .count
330
+ * sizeof (struct resource_directory ));
331
+ for (i = 0 ; i < icon .count ; i ++ ) {
332
+ UpdateResource (handle , RT_ICON ,
333
+ MAKEINTRESOURCE (id ++ ), language ,
334
+ icon .images [i ],
335
+ icon .items [i ].bytes_in_resource );
336
+ }
337
+ }
338
+
216
339
if (command_count >= 0 ) {
217
340
LPWSTR buffer , p ;
218
341
int alloc = 16 ; /* 16 words with string lengths, for sure... */
@@ -262,12 +385,15 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
262
385
wargv = CommandLineToArgvW (cmdline , & wargc );
263
386
264
387
if (wargv [1 ]) {
388
+ if (wargc == 4 && !wcscmp (wargv [1 ], L"icon" ))
389
+ exit (edit_resources (wargv [2 ], wargv [3 ],
390
+ NULL , -1 ));
265
391
if (wargc > 1 && !wcscmp (wargv [1 ], L"command" ))
266
- exit (edit_resources (wargv [2 ],
392
+ exit (edit_resources (wargv [2 ], NULL ,
267
393
wargv + 3 , wargc - 3 ));
268
394
}
269
395
fwprintf (stderr ,
270
- L"Usage: %s command <exe> <args>...\n" ,
396
+ L"Usage: %s (icon | command) <exe> <args>...\n" ,
271
397
basename );
272
398
exit (1 );
273
399
}
0 commit comments