Chameleon

Chameleon Svn Source Tree

Root/branches/meklort/i386/modules/KextPatcher/kext_patcher.c

Source at commit 613 created 9 years 1 month ago.
By meklort, Typo fix
1/*
2 * Copyright (c) 2010 Evan Lojewski. All rights reserved.
3 *
4 *KextPather
5 *This is an experimental module that I'm looking into implimenting.
6 *The main purpose is to replace the need for programs such as
7 * NetbookInstaller's kext patching routines. THis way, Apple's kexts can be
8 * patched whe loaded instead. (eg: GMA950 kext, Bluetooth + Wifi kexts)
9 */
10
11#include "libsaio.h"
12#include "zlib.h"
13#include "kext_patcher.h"
14#include "boot.h"
15#include "bootstruct.h"
16#include "pci.h"
17#include "drivers.h"
18#include "mkext.h"
19#include "modules.h"
20#include "hex_editor.h"
21
22
23#define kHDACodec"HDACodec"/* acpi_patcher.c */
24
25
26#ifndef DEBUG_KEXT_PATCHER
27#define DEBUG_KEXT_PATCHER 0
28#endif
29
30#if DEBUG_KEXT_PATCHER
31#define DBG(x...)printf(x)
32#else
33#define DBG(x...)
34#endif
35bool patch_kext(TagPtr plist, char* plistbuffer, void* start);
36bool patch_gma_kexts(TagPtr plist, char* plistbuffer, void* start);
37bool patch_bcm_kext(TagPtr plist, char* plistbuffer, void* start);
38bool patch_hda_kext(TagPtr plist, char* plistbuffer, void* start);
39bool patch_hda_controller(TagPtr plist, char* plistbuffer, void* start);
40
41int chartohex(char c);
42
43static void * z_alloc(void *, u_int items, u_int size);
44static void z_free(void *, void *ptr);
45
46uint16_t patch_gma_deviceid = 0;
47uint16_t patch_bcm_deviceid = 0;
48// TODO: add detection code / a method for users to enter the id
49uint16_t patch_hda_codec = 0;
50
51#define NEEDS_PATCHING(patch_bcm_deviceid || patch_gma_deviceid || patch_hda_codec)
52
53typedef struct z_mem {
54 uint32_t alloc_size;
55 uint8_t data[0];
56} z_mem;
57
58/*
59 * Space allocation and freeing routines for use by zlib routines.
60 */
61void *
62z_alloc(void * notused __unused, u_int num_items, u_int size)
63{
64 void * result = NULL;
65 z_mem * zmem = NULL;
66 uint32_t total = num_items * size;
67 uint32_t allocSize = total + sizeof(zmem);
68
69 zmem = (z_mem *)malloc(allocSize);
70 if (!zmem) {
71 goto finish;
72 }
73 zmem->alloc_size = allocSize;
74 result = (void *)&(zmem->data);
75finish:
76 return result;
77}
78
79void
80z_free(void * notused __unused, void * ptr)
81{
82 uint32_t * skipper = (uint32_t *)ptr - 1;
83 z_mem * zmem = (z_mem *)skipper;
84 free((void *)zmem);
85 return;
86}
87
88
89unsigned long Mkext_Alder32( unsigned char * buffer, long length );
90
91void KextPatcher_hook(void* current, void* arg2, void* arg3, void* arg4);
92
93/**
94 ** KextPatcher_start -> module start
95 **Notified the module system that this module will hook into the
96 **LoadMatchedModules and LoadDriverMKext functions
97 **/
98void KextPatcher_start()
99{
100// Hooks into the following:
101//execute_hook("LoadDriverMKext", (void*)package, (void*) length, NULL, NULL);
102// execute_hook("LoadMatchedModules", module, &length, executableAddr, NULL);
103
104register_hook_callback("PCIDevice", &KextPatcher_hook);
105//register_hook_callback("LoadMatchedModules", &kext_loaded);
106register_hook_callback("LoadDriverMKext", &mkext_loaded);
107
108}
109
110/**
111 ** kext_loaded -> Called whenever a kext is in read into memory
112 **This function will be used to patch kexts ( eg AppleInteIntegratedFramebuffer)
113 **and their plists when they are loaded into memmory
114 **/
115void kext_loaded(void* moduletmp, void* lengthprt, void* executableAddr, void* arg3)
116{
117
118//ModulePtr module = moduletmp;
119//long length = *(long*)lengthprt;
120//long length2 = strlen(module->plistAddr);
121// *(long*)lengthprt = length2 + 5 * 1024 * 1024;
122
123//printf("Loading %s, lenght is %d, executable is 0x%X\n", module->plistAddr, length, executableAddr);
124//getc();
125}
126
127/**
128 ** mkext_loaded -> Called whenever an mkext is in read into memory
129 **This function will be used to patch mkext. Matching kexts will be
130 **Extracted, modified, and then compressed again. Note: I need to determine
131 **what sort of slowdown this will cause and if it's worth implimenting.
132 **/
133
134void mkext_loaded(void* filespec, void* packagetmp, void* lengthtmp, void* arg3)
135{
136const char* hda_codec;
137int len = 0;
138
139if (getValueForKey(kHDACodec, &hda_codec, &len, &bootInfo->bootConfig))
140{
141int index = 0;
142while(len)
143{
144patch_hda_codec <<= 4;
145patch_hda_codec |= chartohex(hda_codec[index]);
146len--;
147index++;
148}
149}
150
151if(!NEEDS_PATCHING) return;// No need to apply a patch, hardware doesn't need it
152
153int version = 0;
154//int length = *((int*)lengthtmp);
155mkext_basic_header* package = packagetmp;
156
157// Verify the MKext.
158 if (( MKEXT_GET_MAGIC(package)!= MKEXT_MAGIC ) ||
159 ( MKEXT_GET_SIGNATURE(package)!= MKEXT_SIGN ) ||
160 ( MKEXT_GET_LENGTH(package)> kLoadSize ) ||
161 ( MKEXT_GET_CHECKSUM(package) !=
162 Mkext_Alder32((unsigned char *)&package->version, MKEXT_GET_LENGTH(package) - 0x10) ) )
163 {
164 return;
165// Don't try to patch a b
166 }
167
168/*
169if(strcmp(filespec, "/System/Library/Caches/com.apple.kext.caches/Startup/Extensions.mkext") == 0)
170{
171printf("Invalidating mkext %s\n", filespec);
172// 10.6 cache folder. Doesn't contain certain extensions we need, so invalidate it.
173//package->adler32++;
174// NOTE: double check that this is needed
175package->magic = 0x00;
176return;
177}*/
178
179
180version = MKEXT_GET_VERSION(package);
181
182if(version == 0x01008000) // mkext1
183{
184// mkext1 uses lzss
185mkext1_header* package = packagetmp;
186int i;
187for(i = 0; i < MKEXT_GET_COUNT(package); i++)
188{
189DBG("Parsing kext %d\n", i);
190//mkext_kext* kext = MKEXT1_GET_KEXT(package, i);
191// uses decompress_lzss
192// TODO: handle kext
193
194}
195}
196else if((version & 0xFFFF0000) == 0x02000000) // mkext2
197{
198DBG("Mkext2 package located at 0x%X\n", package);
199
200// mkext2 uses zlib
201mkext2_header* package = packagetmp;
202z_stream zstream;
203bool zstream_inited = false;
204int zlib_result;
205int plist_offset = MKEXT2_GET_PLIST(package);
206
207char* plist = malloc(MKEXT2_GET_PLIST_FULLSIZE(package));
208
209bzero(&zstream, sizeof(zstream));
210zstream.next_in = (UInt8*)((char*)package + plist_offset);
211zstream.avail_in = MKEXT2_GET_PLIST_COMPSIZE(package);
212
213zstream.next_out = (UInt8*)plist;
214zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package);
215
216zstream.zalloc = z_alloc;
217zstream.zfree = z_free;
218
219zlib_result = inflateInit(&zstream);
220if (Z_OK != zlib_result)
221{
222printf("ZLIB Error: %s\n", zstream.msg);
223getc();
224}
225else
226{
227zstream_inited = true;
228}
229
230
231zlib_result = inflate(&zstream, Z_FINISH);
232if (zstream_inited) inflateEnd(&zstream);
233
234DBG("Inflated result is %d, in: %d bytes, out: %d bytes\n", zlib_result, zstream.total_in, zstream.total_out);
235if (zlib_result == Z_STREAM_END || zlib_result == Z_OK)
236{
237config_file_t plistData;
238config_file_t allDicts;
239bzero(&plistData, sizeof(plistData));
240bzero(&allDicts, sizeof(allDicts));
241
242XMLParseFile( plist, &plistData.dictionary );
243
244int count = 0;
245
246allDicts.dictionary = XMLGetProperty(plistData.dictionary, kMKEXTInfoDictionariesKey);
247count = XMLTagCount(allDicts.dictionary);
248
249DBG("Plist contains %d kexts\n", count);
250
251
252bool patched = false;
253for(; count--; count > 0)
254{
255TagPtr kextEntry = XMLGetElement(allDicts.dictionary, count);
256patched |= patch_kext(kextEntry, plist, package);
257}
258
259
260if(patched)
261{
262zstream_inited = false;
263// Recompress the plist
264bzero(&zstream, sizeof(zstream));
265zstream.next_in = (UInt8*)plist;
266zstream.next_out = (UInt8*)package + plist_offset;
267zstream.avail_in = MKEXT2_GET_PLIST_FULLSIZE(package);
268zstream.avail_out = MKEXT2_GET_PLIST_FULLSIZE(package)<<2;// Give us some extra free space, just in case
269zstream.zalloc = Z_NULL;
270zstream.zfree = Z_NULL;
271zstream.opaque = Z_NULL;
272
273
274zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);
275if (Z_OK != zlib_result) {
276printf("ZLIB Deflate Error: %s\n", zstream.msg);
277getc();
278}
279else
280{
281zstream_inited = true;
282}
283
284zlib_result = deflate(&zstream, Z_FINISH);
285
286if (zlib_result == Z_STREAM_END)
287{
288DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, MKEXT2_GET_PLIST_FULLSIZE(package));
289}
290else if (zlib_result == Z_OK)
291{
292/* deflate filled output buffer, meaning the data doesn't compress.
293 */
294DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, MKEXT2_GET_PLIST_FULLSIZE(package));
295
296}
297else if (zlib_result != Z_STREAM_ERROR)
298{
299printf("ZLIB Deflate Error: %s\n", zstream.msg);
300getc();
301}
302
303if(zstream.total_out != MKEXT2_GET_PLIST_COMPSIZE(package))
304{
305// Update the mkext length
306MKEXT2_HDR_CAST(package)->length = MKEXT_SWAP(MKEXT_GET_LENGTH(package) - MKEXT2_GET_PLIST_COMPSIZE(package) + zstream.total_out);
307MKEXT2_HDR_CAST(package)->plist_compressed_size = MKEXT_SWAP(zstream.total_out);
308*((int*)lengthtmp) -= MKEXT2_GET_PLIST_COMPSIZE(package);
309*((int*)lengthtmp) += zstream.total_out;
310}
311
312if (zstream_inited) deflateEnd(&zstream);
313
314
315
316// re alder32 the new mkext2 package
317MKEXT_HDR_CAST(package)->adler32 =
318MKEXT_SWAP(Mkext_Alder32((unsigned char *)&package->version,
319 MKEXT_GET_LENGTH(package) - 0x10));
320}
321}
322else
323{
324printf("ZLIB Error: %s\n", zstream.msg);
325getc();
326}
327
328//config_file_t mkextPlist;
329//ParseXMLFile((char*) plist, &mkextPlist.dictionary);
330
331
332
333
334
335/*int i;
336for(i = 0; i < MKEXT_GET_COUNT(package); i++)
337{
338printf("Parsing kext %d\n", i);
339}
340*/
341
342
343}
344
345
346DBG("Loading %s, version 0x%x\n", filespec, version);
347//getc();
348}
349
350// FIXME: only handles mkext2 entries
351bool patch_kext(TagPtr plist, char* plistbuffer, void* start)
352{
353char* bundleID;
354
355if(XMLGetProperty(plist, kMKEXTExecutableKey) == NULL) return false;// Kext is a plist only kext, don't patch
356
357bundleID = XMLCastString(XMLGetProperty(plist, kPropCFBundleIdentifier));
358
359
360if(patch_gma_deviceid &&
361 (
362(strcmp(bundleID, "com.apple.driver.AppleIntelGMA950") == 0) ||
363(strcmp(bundleID, "com.apple.driver.AppleIntelIntegratedFramebuffer") == 0)
364 )
365 )
366{
367return patch_gma_kexts(plist, plistbuffer, start);
368}
369else if(patch_bcm_deviceid && (strcmp(bundleID, "com.apple.driver.AirPortBrcm43xx") == 0))
370{
371return patch_bcm_kext(plist, plistbuffer, start);
372
373}
374else if(patch_hda_codec && strcmp(bundleID, "com.apple.driver.AppleHDA") == 0)
375{
376return patch_hda_kext(plist, plistbuffer, start);
377
378}
379/*
380else if(patch_hda_codec && strcmp(bundleID, "com.apple.driver.AppleHDAController") == 0)
381{
382return patch_hda_controller(plist, plistbuffer, start);
383
384}
385*/
386return false;
387}
388
389void KextPatcher_hook(void* arg1, void* arg2, void* arg3, void* arg4)
390{
391pci_dt_t* current = arg1;
392if(current)
393{
394switch(current->class_id)
395{
396case PCI_CLASS_DISPLAY_VGA:
397if(current->vendor_id == 0x8086 &&
398 (
399current->device_id == 0x27AE /*||
400
401current->device_id == 0xA001 ||
402current->device_id == 0xA002 ||
403current->device_id == 0xA011 ||
404current->device_id == 0xA012
405 */
406
407)
408 )
409{
410patch_gma_deviceid = current->device_id;
411}
412break;
413
414case PCI_CLASS_NETWORK_OTHER:
415
416// Patch BCM43xx
417if(current->vendor_id == 0x14E4 && ((current->device_id & 0xFF00) == 0x4300))
418{
419patch_bcm_deviceid = current->device_id;
420}
421break;
422}
423}
424}
425
426
427bool patch_hda_controller(TagPtr plist, char* plistbuffer, void* start)
428{
429return false;
430// change the PCI class code to match to. Note: A LegacyHDA plist should do this on it's own
431// As such, it's disabled
432
433// TODO: read class code
434TagPtr personality;
435personality =XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));
436personality =XMLGetProperty(personality, (const char*)"BuiltInHDA");
437TagPtr match_class =XMLCastArray(XMLGetProperty(personality, (const char*)"IOPCIClassMatch"));
438
439
440char* new_str = malloc(strlen("0xXXXX000&0xFFFE0000")+1);
441sprintf(new_str, "0x04030000&amp;0xFFFE0000"); // todo, pass in actual class id
442
443
444char* orig_string = "0x04020000&amp;0xFFFE0000"; //XMLCastString(match_class);
445
446DBG("Attemting to replace '%s' with '%s'\n", orig_string, new_str);
447
448// TODO: verify string doesn't exist first.
449
450replace_string(orig_string, new_str, plistbuffer + XMLCastStringOffset(match_class), 10240);
451
452return true;
453
454}
455
456
457bool patch_hda_kext(TagPtr plist, char* plistbuffer, void* start)
458{
459uint16_t find_codec = 0;
460int full_size, compressed_size, executable_offset;
461void* compressed_data;
462mkext2_file_entry* kext;
463int zlib_result;
464z_stream zstream;
465bool zstream_inited = false;
466
467switch(0xFF00 & patch_hda_codec)
468{
469case 0x0200:
470find_codec = 0x0262;
471break;
472
473case 0x0800:
474find_codec = 0x0885;
475break;
476
477case 0x0600:// specificaly the 662
478find_codec = 0x0885;
479break;
480}
481
482if(!find_codec) return false;// notify caller that we aren't patching the kext
483
484
485executable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));
486kext = (void*)((char*)start + executable_offset);
487
488full_size = MKEXT2_GET_ENTRY_FULLSIZE(kext);
489compressed_size = MKEXT2_GET_ENTRY_COMPSIZE(kext);
490compressed_data = MKEXT2_GET_ENTRY_DATA(kext);
491executable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));
492
493
494char* executable = malloc(full_size);
495
496bzero(&zstream, sizeof(zstream));
497zstream.next_in = (UInt8*)compressed_data;
498zstream.avail_in = compressed_size;
499
500zstream.next_out = (UInt8*)executable;
501zstream.avail_out = full_size;
502
503zstream.zalloc = z_alloc;
504zstream.zfree = z_free;
505
506zlib_result = inflateInit(&zstream);
507if (Z_OK != zlib_result)
508{
509printf("ZLIB Inflate Error: %s\n", zstream.msg);
510getc();
511}
512else
513{
514zstream_inited = true;
515}
516
517
518zlib_result = inflate(&zstream, Z_FINISH);
519
520DBG("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);
521
522replace_word(0x10EC | (find_codec << 16), 0xE10EC | (patch_hda_codec << 16), executable, zstream.total_out);
523
524if (zstream_inited) inflateEnd(&zstream);
525
526
527zstream.next_in = (UInt8*)executable;
528zstream.next_out = (UInt8*)compressed_data;
529
530zstream.avail_in = full_size;
531zstream.avail_out = compressed_size;
532zstream.zalloc = Z_NULL;
533zstream.zfree = Z_NULL;
534zstream.opaque = Z_NULL;
535
536
537
538// Recompress the eecutable
539zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);
540if (Z_OK != zlib_result) {
541printf("ZLIB Deflate Error: %s\n", zstream.msg);
542getc();
543}
544else
545{
546zstream_inited = true;
547}
548
549zlib_result = deflate(&zstream, Z_FINISH);
550
551if (zlib_result == Z_STREAM_END)
552{
553DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);
554}
555else if (zlib_result == Z_OK)
556{
557/* deflate filled output buffer, meaning the data doesn't compress.
558 */
559DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);
560
561}
562else if (zlib_result != Z_STREAM_ERROR)
563{
564printf("ZLIB Deflate Error: %s\n", zstream.msg);
565getc();
566}
567
568if (zstream_inited) deflateEnd(&zstream);
569
570free(executable);
571
572return true;
573
574}
575
576bool patch_bcm_kext(TagPtr plist, char* plistbuffer, void* start)
577{
578TagPtr personality;
579personality =XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));
580personality =XMLGetProperty(personality, (const char*)"Broadcom 802.11 PCI");
581TagPtr match_names =XMLCastArray(XMLGetProperty(personality, (const char*)"IONameMatch"));
582
583
584char* new_str = malloc(strlen("pci14e4,xxxx")+1);
585sprintf(new_str, "pci14e4,%02x", patch_bcm_deviceid);
586
587// Check to see if we *really* need to modify the plist, if not, return false
588// so that *if* this were going ot be the only modified kext, the repacking code
589// won't need to be executed.
590int count = XMLTagCount(match_names);
591while(count)
592{
593count--;
594TagPtr replace =XMLGetElement(match_names, count);// Modify the second entry
595char* orig_string = XMLCastString(replace);
596if(strcmp(orig_string, new_str) == 0) return false;
597}
598
599
600TagPtr replace =XMLGetElement(match_names, 1);// Modify the second entry
601char* orig_string = XMLCastString(replace);
602
603
604// TODO: verify string doesn't exist first.
605
606replace_string(orig_string, new_str, plistbuffer + XMLCastStringOffset(replace), 10240);
607
608return true;
609}
610
611bool patch_gma_kexts(TagPtr plist, char* plistbuffer, void* start)
612{
613int exeutable_offset, full_size, compressed_size;
614TagPtr personality;
615long offset;
616int zlib_result;
617z_stream zstream;
618bool zstream_inited = false;
619mkext2_file_entry* kext;
620void* compressed_data;
621
622exeutable_offset = XMLCastInteger(XMLGetProperty(plist, kMKEXTExecutableKey));
623kext = (void*)((char*)start + exeutable_offset);
624
625full_size = MKEXT2_GET_ENTRY_FULLSIZE(kext);
626compressed_size = MKEXT2_GET_ENTRY_COMPSIZE(kext);
627compressed_data = MKEXT2_GET_ENTRY_DATA(kext);
628
629personality =XMLCastDict(XMLGetProperty(plist, kPropIOKitPersonalities));
630if(XMLGetProperty(personality, (const char*)"Intel915"))
631{
632personality =XMLGetProperty(personality, (const char*)"Intel915");
633}
634else
635{
636personality =XMLGetProperty(personality, (const char*)"AppleIntelIntegratedFramebuffer");
637}
638#if DEBUG_KEXT_PATCHER
639char* pcimatch =XMLCastString(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));
640#endif
641offset =XMLCastStringOffset(XMLGetProperty(personality, (const char*)"IOPCIPrimaryMatch"));
642
643char* newstring = malloc(strlen("0x27A28086") + 1);
644sprintf(newstring, "0x%04x", 0x8086 | (patch_gma_deviceid << 16));
645
646DBG("Replacing %s with %s\n", "0x27A28086", newstring);
647replace_string("0x27A28086", newstring, plistbuffer + offset, 10240);
648
649char* executable = malloc(full_size);
650
651bzero(&zstream, sizeof(zstream));
652zstream.next_in = (UInt8*)compressed_data;
653zstream.avail_in = compressed_size;
654
655zstream.next_out = (UInt8*)executable;
656zstream.avail_out = full_size;
657
658zstream.zalloc = z_alloc;
659zstream.zfree = z_free;
660
661zlib_result = inflateInit(&zstream);
662if (Z_OK != zlib_result)
663{
664printf("ZLIB Inflate Error: %s\n", zstream.msg);
665getc();
666}
667else
668{
669zstream_inited = true;
670}
671
672
673zlib_result = inflate(&zstream, Z_FINISH);
674
675DBG("Inflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);
676
677replace_word(0x27A28086, 0x8086 | (patch_gma_deviceid << 16), executable, zstream.total_out);
678if (zstream_inited) inflateEnd(&zstream);
679
680
681zstream.next_in = (UInt8*)executable;
682//zstream.next_out = (UInt8*)((int)compressed_data<<1);
683zstream.next_out = (UInt8*)compressed_data;
684
685zstream.avail_in = full_size;
686zstream.avail_out = compressed_size;
687zstream.zalloc = Z_NULL;
688zstream.zfree = Z_NULL;
689zstream.opaque = Z_NULL;
690
691
692
693// Recompress the eecutable
694zlib_result = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,15, 8 /* memLevel */, Z_DEFAULT_STRATEGY);
695if (Z_OK != zlib_result) {
696printf("ZLIB Deflate Error: %s\n", zstream.msg);
697getc();
698}
699else
700{
701zstream_inited = true;
702}
703
704zlib_result = deflate(&zstream, Z_FINISH);
705
706if (zlib_result == Z_STREAM_END)
707{
708DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);
709}
710else if (zlib_result == Z_OK)
711{
712/* deflate filled output buffer, meaning the data doesn't compress.
713 */
714DBG("Deflated result is %d, in: %d bytes, out: %d bytes, full: %d\n", zlib_result, zstream.total_in, zstream.total_out, full_size);
715
716}
717else if (zlib_result != Z_STREAM_ERROR)
718{
719printf("ZLIB Deflate Error: %s\n", zstream.msg);
720getc();
721}
722
723if (zstream_inited) deflateEnd(&zstream);
724
725free(executable);
726
727return true;
728}
729
730int chartohex(char c)
731{
732if(c <= '9' && c >= '0')
733{
734return c - '0';// c is between 0 and 9
735}
736else if(c <= 'F' && c >= 'A')
737{
738return c - 'A' + 10; // c = 10 - 15;
739}
740else if(c <= 'f' && c >= 'a')
741{
742return c - 'a' + 10; // c = 10 - 15;
743}
744return 0;
745}

Archive Download this file

Revision: 613