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

Add FFI::LastError.win_error #633

Merged
merged 3 commits into from Jan 6, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 47 additions & 2 deletions ext/ffi_c/LastError.c
Expand Up @@ -49,8 +49,17 @@
# define USE_PTHREAD_LOCAL
#endif

#if defined(__CYGWIN__)
typedef uint32_t DWORD;
DWORD __stdcall GetLastError(void);
void __stdcall SetLastError(DWORD);
#endif

typedef struct ThreadData {
int td_errno;
#if defined(_WIN32) || defined(__CYGWIN__)
DWORD td_winapi_errno;
#endif
} ThreadData;

#if defined(USE_PTHREAD_LOCAL)
Expand Down Expand Up @@ -126,6 +135,19 @@ get_last_error(VALUE self)
return INT2NUM(thread_data_get()->td_errno);
}

#if defined(_WIN32) || defined(__CYGWIN__)
/*
* call-seq: winapi_error
* @return [Numeric]
* Get +GetLastError()+ value. Only Windows or Cygwin.
*/
static VALUE
get_last_winapi_error(VALUE self)
{
return INT2NUM(thread_data_get()->td_winapi_errno);
}
#endif


/*
* call-seq: error(error)
Expand All @@ -146,22 +168,40 @@ set_last_error(VALUE self, VALUE error)
return Qnil;
}

#if defined(_WIN32) || defined(__CYGWIN__)
/*
* call-seq: error(error)
* @param [Numeric] error
* @return [nil]
* Set +GetLastError()+ value. Only on Windows and Cygwin.
*/
static VALUE
set_last_winapi_error(VALUE self, VALUE error)
{
SetLastError(NUM2INT(error));
return Qnil;
}
#endif


void
rbffi_save_errno(void)
{
int error = 0;

#ifdef _WIN32
error = GetLastError();
#else
error = errno;
#endif

#if defined(_WIN32) || defined(__CYGWIN__)
DWORD winapi_error = GetLastError();
thread_data_get()->td_winapi_errno = winapi_error;
#endif

thread_data_get()->td_errno = error;
}


void
rbffi_LastError_Init(VALUE moduleFFI)
{
Expand All @@ -175,6 +215,11 @@ rbffi_LastError_Init(VALUE moduleFFI)
rb_define_module_function(moduleError, "error", get_last_error, 0);
rb_define_module_function(moduleError, "error=", set_last_error, 1);

#if defined(_WIN32) || defined(__CYGWIN__)
rb_define_module_function(moduleError, "winapi_error", get_last_winapi_error, 0);
rb_define_module_function(moduleError, "winapi_error=", set_last_winapi_error, 1);
#endif

#if defined(USE_PTHREAD_LOCAL)
pthread_key_create(&threadDataKey, thread_data_free);
#else
Expand Down