#include <windows.h> #include <stdlib.h> #include <stdio.h> ///////////////////////////////////////////////////////////////////////// _inline size_t stepToNextMarker(unsigned char* mem, size_t j, size_t len) { size_t tmp = j + (mem[j] << 8 | mem[j + 1]); if(tmp < len && 0xff == mem[tmp]) //check if in range and next marker exists j = tmp; return j; } ///////////////////////////////////////////////////////////////////////// size_t scanJpeg(unsigned char* mem, size_t len, unsigned char** outPtr) { size_t j, ret, tmp; unsigned char c, *ptr = NULL, *lastEoi = NULL; for(ret = j = 0; j < len; ) { if(0xff == mem[j++]) { if(j >= len) break; c = mem[j++]; if(j >= len) break; switch(c) { case 0xd8: printf("SOI (ffd8)\t@%p\n", j - 2); break; case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: printf("APP%d(ffe%x)\t@%p\n", c & 0xf, c & 0xf, j - 2); j = stepToNextMarker(mem, j, len); break; case 0xc4: printf("DHT (ffc4)\t@%p\n", j - 2); j = stepToNextMarker(mem, j, len); break; case 0xdb: printf("DQT (ffdb)\t@%p\n", j - 2); j = stepToNextMarker(mem, j, len); break; case 0xd9: printf("EOI (ffd9)\t@%p\n", j - 2); //end of image is the last marker ptr = lastEoi; lastEoi = &mem[j - 2]; break; case 0xc0: //most markers except c0 and c2 are unused case 0xc1: case 0xc2: case 0xc3: case 0xc5: case 0xc6: case 0xc7: case 0xc9: case 0xca: case 0xcb: case 0xcd: case 0xce: case 0xcf: printf("SOF%d(ffc%x)\t@%p\tx=%d, y=%d\n", c & 0xf, c & 0xf, j - 2, mem[j + 5] << 8 | mem[j + 6], mem[j + 3] << 8 | mem[j + 4]); j = stepToNextMarker(mem, j, len); break; case 0xda: printf("SOS (ffda)\t@%p\n", j - 2); tmp = j + (mem[j] << 8 | mem[j + 1]); //the compressed stream follows, no next marker if(tmp < len) j = tmp; break; case 0xfe: printf("COM (fffe)\t@%p\n", j - 2); j = stepToNextMarker(mem, j, len); break; case 0xdd: printf("DRI (ffdd)\t@%p\n", j - 2); j = stepToNextMarker(mem, j, len); break; } } } if(ptr) { ret = lastEoi - ptr + 2; *outPtr = ptr; } return ret; } /////////////////////////////////////////////////////////////////////////////////////////////////////////// int repairJpg(char* fName) { HANDLE h; size_t len, tmp; unsigned char *mem, *ptr; h = CreateFile(fName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(h == INVALID_HANDLE_VALUE) { printf("Error while opening a \"%s\"\n", fName); return -1; } len = GetFileSize(h, NULL); mem = VirtualAlloc(NULL, len, MEM_COMMIT, PAGE_READWRITE); ReadFile(h, mem, len, &tmp, NULL); len = scanJpeg(mem, len, &ptr); if(len) { ptr[1] = 0xd8; SetFilePointer(h, 0, NULL, FILE_BEGIN); WriteFile(h, ptr, len, &tmp, NULL); SetEndOfFile(h); } VirtualFree(mem, 0, MEM_RELEASE); CloseHandle(h); return 0; } /////////////////////////////////////////////////////////////////////////////////////////////////////////// int main() { char buf[MAX_PATH]; int len; WIN32_FIND_DATA fd; HANDLE h; len = GetModuleFileName(NULL, buf, sizeof(buf)); for( ; len && buf[len] != '\\'; --len) ; strcpy(&buf[len], "\\*.jpg"); h = FindFirstFile(buf, &fd); if(INVALID_HANDLE_VALUE == h) { printf("Jpg file(s) not found.\nCopy a parseJpg.exe to directory with jpg file(s) and run again.\n"); getch(); return -1; } do { strcpy(&buf[len + 1], fd.cFileName); printf("Repairing \"%s\"\n", buf); repairJpg(buf); } while(FindNextFile(h, &fd)); FindClose(h); printf("\nDone.\n"); return 0; } |