Skip to content

Commit

Permalink
Fix multiple issues with MSVC Windows build (#178)
Browse files Browse the repository at this point in the history
* Add MSVC files and CTestTestfile  to .gitignore

* Add dllexport to exported symbols in DLL build

* Handle backslashes in paths on Windows
  • Loading branch information
elasota authored Jan 3, 2024
1 parent 082df8d commit bfba780
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 28 deletions.
19 changes: 19 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,22 @@ src/unshield-deobfuscate
.idea
build
/cmake-build-debug/
.vs
*.sln
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
DartConfiguration.tcl
CTestTestfile.cmake
*.tlog
*.obj
*.FileListAbsolute.txt
*.lastbuildstate
*.log
*.pdb
*.lib
*.recipe
*.exp
*.ilk
*.exe
*.dll
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ if(BUILD_STATIC)
add_library(libunshield STATIC ${LIBUNSHIELD_HEADERS} ${LIBUNSHIELD_SOURCES})
else()
add_library(libunshield SHARED ${LIBUNSHIELD_HEADERS} ${LIBUNSHIELD_SOURCES})
add_compile_definitions(LIBUNSHIELD_DYNAMIC_LIBRARY)
endif()

target_include_directories(libunshield PUBLIC
Expand Down
20 changes: 18 additions & 2 deletions lib/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ long int unshield_get_path_max(Unshield* unshield)

char *unshield_get_base_directory_name(Unshield *unshield) {
long int path_max = unshield_get_path_max(unshield);
char *p = strrchr(unshield->filename_pattern, '/');
char *p = unshield_get_last_path_separator(unshield->filename_pattern);
char *dirname = malloc(path_max);

if (p) {
Expand Down Expand Up @@ -95,7 +95,7 @@ FILE* unshield_fopen_for_reading(Unshield* unshield, int index, const char* suff
DIR *sourcedir = NULL;
long int path_max = unshield_get_path_max(unshield);

q=strrchr(filename,'/');
q=unshield_get_last_path_separator(filename);
if (q)
q++;
else
Expand Down Expand Up @@ -202,6 +202,22 @@ uint8_t* unshield_header_get_buffer(Header* header, uint32_t offset)
return NULL;
}

/**
Returns the last path separator in a filesystem path
*/
char *unshield_get_last_path_separator(char *path)
{
char *p = strrchr(path, '/');

#ifdef WIN32
char *pbs = strrchr(path, '\\');

if (NULL != pbs && (NULL == p || pbs > p))
return pbs;
#endif

return p;
}

static int unshield_strlen_utf16(const uint16_t* utf16)
{
Expand Down
1 change: 1 addition & 0 deletions lib/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ bool unshield_read_common_header(uint8_t** buffer, CommonHeader* common);
const char* unshield_get_utf8_string(Header* header, const void* buffer);
const char* unshield_header_get_string(Header* header, uint32_t offset);
uint8_t* unshield_header_get_buffer(Header* header, uint32_t offset);
char *unshield_get_last_path_separator(char *path);

static inline void* unshield_fopen(Unshield* unshield, const char *filename, const char *modes)
{
Expand Down
2 changes: 1 addition & 1 deletion lib/libunshield.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ static bool unshield_create_filename_pattern(Unshield* unshield, const char* fil
{
char pattern[256];
char* prefix = strdup(filename);
char* p = strrchr(prefix, '/');
char* p = unshield_get_last_path_separator(prefix);
if (!p)
p = prefix;

Expand Down
54 changes: 30 additions & 24 deletions lib/libunshield.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
#ifdef __cplusplus
extern "C" {
#endif

#if defined(_MSC_VER) && defined(LIBUNSHIELD_DYNAMIC_LIBRARY)
#define UNSHIELD_DLLEXPORT __declspec(dllexport)
#else
#define UNSHIELD_DLLEXPORT
#endif

typedef struct _Unshield Unshield;

Expand All @@ -24,16 +30,16 @@ typedef struct _Unshield Unshield;
Logging
*/

void unshield_set_log_level(int level);
UNSHIELD_DLLEXPORT void unshield_set_log_level(int level);


/*
Open/close functions
*/

Unshield* unshield_open(const char* filename);
Unshield* unshield_open_force_version(const char* filename, int version);
void unshield_close(Unshield* unshield);
UNSHIELD_DLLEXPORT Unshield* unshield_open(const char* filename);
UNSHIELD_DLLEXPORT Unshield* unshield_open_force_version(const char* filename, int version);
UNSHIELD_DLLEXPORT void unshield_close(Unshield* unshield);

typedef struct
{
Expand All @@ -48,8 +54,8 @@ typedef struct
struct dirent* (*readdir)(void *dir, void *userdata);
} UnshieldIoCallbacks;

Unshield* unshield_open2(const char* filename, const UnshieldIoCallbacks* callbacks, void* userdata);
Unshield* unshield_open2_force_version(const char* filename, int version, const UnshieldIoCallbacks* callbacks, void* userdata);
UNSHIELD_DLLEXPORT Unshield* unshield_open2(const char* filename, const UnshieldIoCallbacks* callbacks, void* userdata);
UNSHIELD_DLLEXPORT Unshield* unshield_open2_force_version(const char* filename, int version, const UnshieldIoCallbacks* callbacks, void* userdata);

/*
Component functions
Expand All @@ -62,8 +68,8 @@ typedef struct
const char** file_group_names;
} UnshieldComponent;

int unshield_component_count (Unshield* unshield);
const char* unshield_component_name (Unshield* unshield, int index);
UNSHIELD_DLLEXPORT int unshield_component_count (Unshield* unshield);
UNSHIELD_DLLEXPORT const char* unshield_component_name (Unshield* unshield, int index);

/*
File group functions
Expand All @@ -76,40 +82,40 @@ typedef struct
unsigned last_file;
} UnshieldFileGroup;

int unshield_file_group_count (Unshield* unshield);
UnshieldFileGroup* unshield_file_group_get (Unshield* unshield, int index);
UnshieldFileGroup* unshield_file_group_find (Unshield* unshield, const char* name);
const char* unshield_file_group_name (Unshield* unshield, int index);
UNSHIELD_DLLEXPORT int unshield_file_group_count (Unshield* unshield);
UNSHIELD_DLLEXPORT UnshieldFileGroup* unshield_file_group_get (Unshield* unshield, int index);
UNSHIELD_DLLEXPORT UnshieldFileGroup* unshield_file_group_find (Unshield* unshield, const char* name);
UNSHIELD_DLLEXPORT const char* unshield_file_group_name (Unshield* unshield, int index);

/*
Directory functions
*/

int unshield_directory_count (Unshield* unshield);
const char* unshield_directory_name (Unshield* unshield, int index);
UNSHIELD_DLLEXPORT int unshield_directory_count (Unshield* unshield);
UNSHIELD_DLLEXPORT const char* unshield_directory_name (Unshield* unshield, int index);

/*
File functions
*/

int unshield_file_count (Unshield* unshield);
const char* unshield_file_name (Unshield* unshield, int index);
bool unshield_file_is_valid (Unshield* unshield, int index);
bool unshield_file_save (Unshield* unshield, int index, const char* filename);
int unshield_file_directory (Unshield* unshield, int index);
size_t unshield_file_size (Unshield* unshield, int index);
UNSHIELD_DLLEXPORT int unshield_file_count (Unshield* unshield);
UNSHIELD_DLLEXPORT const char* unshield_file_name (Unshield* unshield, int index);
UNSHIELD_DLLEXPORT bool unshield_file_is_valid (Unshield* unshield, int index);
UNSHIELD_DLLEXPORT bool unshield_file_save (Unshield* unshield, int index, const char* filename);
UNSHIELD_DLLEXPORT int unshield_file_directory (Unshield* unshield, int index);
UNSHIELD_DLLEXPORT size_t unshield_file_size (Unshield* unshield, int index);

/** For investigation of compressed data */
bool unshield_file_save_raw(Unshield* unshield, int index, const char* filename);
UNSHIELD_DLLEXPORT bool unshield_file_save_raw(Unshield* unshield, int index, const char* filename);

/** Maybe it's just gzip without size? */
bool unshield_file_save_old(Unshield* unshield, int index, const char* filename);
UNSHIELD_DLLEXPORT bool unshield_file_save_old(Unshield* unshield, int index, const char* filename);

/** Deobfuscate a buffer. Seed is 0 at file start */
void unshield_deobfuscate(unsigned char* buffer, size_t size, unsigned* seed);
UNSHIELD_DLLEXPORT void unshield_deobfuscate(unsigned char* buffer, size_t size, unsigned* seed);

/** Is the archive Unicode-capable? */
bool unshield_is_unicode(Unshield* unshield);
UNSHIELD_DLLEXPORT bool unshield_is_unicode(Unshield* unshield);

#ifdef __cplusplus
}
Expand Down
22 changes: 21 additions & 1 deletion src/unshield.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,35 @@ static bool make_sure_directory_exists(const char* directory)/*{{{*/
p+=2;
else if (0 == strncmp(p, "../", 3))
p+=3;
#ifdef WIN32
if ('\\' == *p)
p++;
else if (0 == strncmp(p, ".\\", 2))
p += 2;
else if (0 == strncmp(p, "..\\", 3))
p += 3;
#endif
else
{
int is_win_root = 0;
const char* slash = strchr(p, '/');
#ifdef WIN32
const char* backslash = strchr(p, '\\');
if (NULL != backslash && (NULL == slash || backslash < slash))
slash = backslash;
#endif

current = strdup(directory);

if (slash)
current[slash-directory] = '\0';

if (stat(current, &dir_stat) < 0)
#ifdef WIN32
if (slash - directory == 2 && current[1] == ':')
is_win_root = 1;
#endif

if (!is_win_root && stat(current, &dir_stat) < 0)
{
#if defined (__MINGW32__) || defined (_WIN32)
if (_mkdir(current) < 0)
Expand Down

0 comments on commit bfba780

Please sign in to comment.