Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix multiple issues with MSVC Windows build #178

Merged
merged 3 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this isn't a private target definition it might leak and cause clients to define it and use dllexport

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You get better optimization if you define it as dllimport for clients

#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