static VALUE string_to_c_strict(VALUE self) { char *s; VALUE num; rb_must_asciicompat(self); s = RSTRING_PTR(self); if (!s || memchr(s, '\0', RSTRING_LEN(self))) rb_raise(rb_eArgError, "string contains null byte"); if (s && s[RSTRING_LEN(self)]) { rb_str_modify(self); s = RSTRING_PTR(self); s[RSTRING_LEN(self)] = '\0'; } if (!s) s = (char *)""; if (!parse_comp(s, 1, &num)) { rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE, self); } return num; }
VALUE rb_str_vcatf(VALUE str, const char *fmt, va_list ap) { rb_printf_buffer_extra buffer; #define f buffer.base VALUE klass; StringValue(str); rb_str_modify(str); f._flags = __SWR | __SSTR; f._bf._size = 0; f._w = rb_str_capacity(str); f._bf._base = (unsigned char *)str; f._p = (unsigned char *)RSTRING_END(str); klass = RBASIC(str)->klass; RBASIC_CLEAR_CLASS(str); f.vwrite = ruby__sfvwrite; f.vextra = ruby__sfvextra; buffer.value = 0; BSD_vfprintf(&f, fmt, ap); RBASIC_SET_CLASS_RAW(str, klass); rb_str_resize(str, (char *)f._p - RSTRING_PTR(str)); #undef f return str; }
static VALUE bug_str_qsort_bang(int argc, VALUE *argv, VALUE str) { VALUE beg, len, size; long l, b = 0, n, s = 1; struct sort_data d; rb_scan_args(argc, argv, "03", &beg, &len, &size); l = RSTRING_LEN(str); if (!NIL_P(beg) && (b = NUM2INT(beg)) < 0 && (b += l) < 0) { rb_raise(rb_eArgError, "out of bounds"); } if (!NIL_P(size) && (s = NUM2INT(size)) < 0) { rb_raise(rb_eArgError, "negative size"); } if (NIL_P(len) || (((n = NUM2INT(len)) < 0) ? (rb_raise(rb_eArgError, "negative length"), 0) : (b + n * s > l))) { n = (l - b) / s; } rb_str_modify(str); d.enc = rb_enc_get(str); d.elsize = s; ruby_qsort(RSTRING_PTR(str) + b, n, s, rb_block_given_p() ? cmp_1 : cmp_2, &d); return str; }
VALUE rb_str_clear( VALUE str) { rb_str_modify( str); rb_str_resize( str, 0); return str; }
/* USB::DevHandle#usb_control_msg(requesttype, request, value, index, bytes, timeout) */ static VALUE rusb_control_msg( VALUE v, VALUE vrequesttype, VALUE vrequest, VALUE vvalue, VALUE vindex, VALUE vbytes, VALUE vtimeout) { usb_dev_handle *p = get_usb_devhandle(v); int requesttype = NUM2INT(vrequesttype); int request = NUM2INT(vrequest); int value = NUM2INT(vvalue); int index = NUM2INT(vindex); int timeout = NUM2INT(vtimeout); char *bytes; int size; int ret; StringValue(vbytes); rb_str_modify(vbytes); bytes = RSTRING_PTR(vbytes); size = RSTRING_LEN(vbytes); ret = usb_control_msg(p, requesttype, request, value, index, bytes, size, timeout); check_usb_error("usb_control_msg", ret); return INT2NUM(ret); }
static VALUE rb_utf_chomp_default(VALUE str) { rb_str_modify(str); const char *end = RSTRING(str)->ptr + RSTRING(str)->len; char *last = utf_find_prev(RSTRING(str)->ptr, end); if (last == NULL) return Qnil; if (_utf_char_validated(last, end) == '\n') { char *last_but_one = utf_find_prev(RSTRING(str)->ptr, last); if (last_but_one != NULL && utf_char(last_but_one) == '\r') last = last_but_one; } else if (!unichar_isnewline(utf_char(last))) { return Qnil; } RSTRING(str)->len -= (RSTRING(str)->ptr + RSTRING(str)->len) - last; *last = '\0'; return str; }
static int read_check(struct io_args *a, long n, const char *msg, int io_wait) { if (n == -1) { if (errno == EINTR) { a->fd = my_fileno(a->io); return -1; } rb_str_set_len(a->buf, 0); if (errno == EAGAIN) { if (io_wait) { (void)kgio_call_wait_readable(a->io); /* buf may be modified in other thread/fiber */ rb_str_modify(a->buf); rb_str_resize(a->buf, a->len); a->ptr = RSTRING_PTR(a->buf); return -1; } else { a->buf = sym_wait_readable; return 0; } } rd_sys_fail(msg); } rb_str_set_len(a->buf, n); if (n == 0) a->buf = Qnil; return 0; }
VALUE rb_str_cut_bang( VALUE str, VALUE len) { int l; #ifdef HAVE_HEADER_RUBY_H #else int n; #endif rb_str_modify( str); l = NUM2INT( len); if (l < 0) l = 0; #ifdef HAVE_HEADER_RUBY_H if (l < RSTRING_LEN( str)) { RSTRING_LEN( str) = l; return str; } #else n = rb_str_strlen( str); if (l < n) { rb_str_update( str, l, n - l, rb_str_new( NULL, 0)); return str; } #endif return Qnil; }
/* * call-seq: * ssl.sysread(length) => string * ssl.sysread(length, buffer) => buffer * * === Parameters * * +length+ is a positive integer. * * +buffer+ is a string used to store the result. */ static VALUE ossl_ssl_read(int argc, VALUE *argv, VALUE self) { SSL *ssl; int ilen, nread = 0; VALUE len, str; rb_scan_args(argc, argv, "11", &len, &str); ilen = NUM2INT(len); if(NIL_P(str)) { str = rb_str_new(0, ilen); } else { StringValue(str); rb_str_modify(str); rb_str_resize(str, ilen); } if(ilen == 0) return str; Data_Get_Struct(self, SSL, ssl); int fd = rb_io_fd(ossl_ssl_get_io(self)); if (ssl) { if(SSL_pending(ssl) <= 0) rb_thread_wait_fd(fd); for (;;) { nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LEN(str)); switch(ssl_get_error(ssl, nread)) { case SSL_ERROR_NONE: goto end; case SSL_ERROR_ZERO_RETURN: rb_eof_error(); case SSL_ERROR_WANT_WRITE: rb_io_wait_writable(fd); continue; case SSL_ERROR_WANT_READ: rb_io_wait_readable(fd); continue; case SSL_ERROR_SYSCALL: if(ERR_peek_error() == 0 && nread == 0) rb_eof_error(); rb_sys_fail(0); default: ossl_raise(eSSLError, "SSL_read:"); } } } else { ID id_sysread = rb_intern("sysread"); rb_warning("SSL session is not started yet."); return rb_funcall(ossl_ssl_get_io(self), id_sysread, 2, len, str); } end: rb_str_set_len(str, nread); OBJ_TAINT(str); return str; }
static VALUE bug_str_cstr_unterm(VALUE str, VALUE c) { long len; rb_str_modify(str); len = RSTRING_LEN(str); RSTRING_PTR(str)[len] = NUM2CHR(c); return str; }
static VALUE pg_tmir_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx ) { t_tmir *this = (t_tmir *) p_typemap; rb_encoding *p_encoding = rb_enc_from_index(enc_idx); VALUE enc = rb_enc_from_encoding(p_encoding); /* field_str is reused in-place by pg_text_dec_copy_row(), so we need to make * a copy of the string buffer for use in ruby space. */ VALUE field_str_copy = rb_str_dup(field_str); rb_str_modify(field_str_copy); return rb_funcall( this->self, s_id_typecast_copy_get, 4, field_str_copy, INT2NUM(fieldno), INT2NUM(format), enc ); }
VALUE rb_str_eat( int argc, VALUE *argv, VALUE str) { VALUE val; int n; int l; int r; #ifdef HAVE_HEADER_RUBY_H n = l = RSTRING_LEN( str); #else n = l = rb_str_strlen( str); #endif if (rb_scan_args( argc, argv, "01", &val) == 1) { if (!NIL_P( val)) { int v = NUM2INT( val); if (v >= 0) { if (n >= v) n = v; } else { n = -n; if (n <= v) n = v; } } } rb_str_modify( str); #ifdef HAVE_HEADER_RUBY_H if (n > 0) { r = l - n; val = rb_str_new5( str, RSTRING_PTR( str), n); memmove( RSTRING_PTR( str), RSTRING_PTR( str) + n, r); } else { r = l + n; val = rb_str_new5( str, RSTRING_PTR( str) + r, -n); } RSTRING_LEN( str) = r; OBJ_INFECT( val, str); #else if (n > 0) { r = 0; } else if (n < 0) { r = l + n; n = -n; } else return Qnil; val = rb_str_substr( str, r, n); if (!NIL_P(val)) rb_str_update( str, r, n, rb_str_new( NULL, 0)); #endif return val; }
VALUE string_xor( int argc, VALUE *argv, VALUE self ) { const char *src = 0; const char *src2 = 0; char *dest = 0 ; size_t length = 0; size_t l; if ( (argc < 1) || (argc > 2) ) { rb_raise( rb_eArgError, "wrong # of arguments(%d for 1 or 2)", argc ); return Qnil; } rb_str_modify(self); dest = RSTRING_PTR(self); length = RSTRING_LEN(self); if ( TYPE(argv[0]) == T_STRING ) { l = RSTRING_LEN(argv[0]); src = RSTRING_PTR(argv[0]); if ( l < length ) length = l; } else { rb_raise( rb_eTypeError, "in method '" "xor" "', argument " "1"" of type '" "String""'" ); return Qnil; } if ( argc == 1 ) { for ( ; length--; ++dest, ++src ) *dest ^= *src; } else { if ( TYPE(argv[1]) == T_STRING ) { l = RSTRING_LEN(argv[1]); src2 = RSTRING_PTR(argv[1]); if ( l < length ) length = l; } else { rb_raise( rb_eTypeError, "in method '" "xor" "', argument " "2"" of type '" "String""'" ); return Qnil; } for ( ; length--; ++dest, ++src, ++src2 ) *dest ^= *src ^ *src2; } return self; }
static void prepare_read(struct io_args *a, int argc, VALUE *argv, VALUE io) { VALUE length; a->io = io; a->fd = my_fileno(io); rb_scan_args(argc, argv, "11", &length, &a->buf); a->len = NUM2LONG(length); if (NIL_P(a->buf)) { a->buf = rb_str_new(NULL, a->len); } else { StringValue(a->buf); rb_str_modify(a->buf); rb_str_resize(a->buf, a->len); } a->ptr = RSTRING_PTR(a->buf); }
/** * Set four bytes for int32 in a binary string and return it. * * @example Set int32 in a BSON string. * rb_string_set_int32(self, pos, int32) * * @param [ String ] self The Ruby binary string. * @param [ Fixnum ] The position to set. * @param [ Fixnum ] The int32 value. * * @return [ String ] The binary string. * * @since 2.0.0 */ static VALUE rb_string_set_int32(VALUE str, VALUE pos, VALUE an_int32) { const int32_t offset = NUM2INT(pos); const int32_t v = NUM2INT(an_int32); const char bytes[4] = { v & 255, (v >> 8) & 255, (v >> 16) & 255, (v >> 24) & 255 }; rb_str_modify(str); if (offset < 0 || offset + 4 > RSTRING_LEN(str)) { rb_raise(rb_eArgError, "invalid position"); } memcpy(RSTRING_PTR(str) + offset, bytes, 4); return str; }
VALUE rb_utf_chomp_bang(int argc, VALUE *argv, UNUSED(VALUE self)) { VALUE str, rs; rb_scan_args(argc, argv, "11", &str, &rs); if (RSTRING(str)->len == 0) return Qnil; if (argc == 1) { rs = rb_rs; if (rs == rb_default_rs) rb_utf_chomp_default(str); } if (NIL_P(rs)) return Qnil; StringValue(rs); long rs_len = RSTRING(rs)->len; if (rs_len == 0) return rb_utf_chomp_newlines(str); long len = RSTRING(str)->len; if (rs_len > len) return Qnil; char last_char = RSTRING(rs)->ptr[rs_len - 1]; if (rs_len == 1 && last_char == '\n') rb_utf_chomp_default(str); char *p = RSTRING(str)->ptr; if (p[len - 1] != last_char || (rs_len > 1 && rb_memcmp(RSTRING(rs)->ptr, p + len - rs_len, rs_len) != 0)) return Qnil; rb_str_modify(str); RSTRING(str)->len -= rs_len; RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; return str; }
/* USB::DevHandle#usb_get_string_simple(index, buf) */ static VALUE rusb_get_string_simple( VALUE v, VALUE vindex, VALUE vbuf) { usb_dev_handle *p = get_usb_devhandle(v); int index = NUM2INT(vindex); char *buf; int buflen; int ret; StringValue(vbuf); rb_str_modify(vbuf); buf = RSTRING_PTR(vbuf); buflen = RSTRING_LEN(vbuf); ret = usb_get_string_simple(p, index, buf, buflen); check_usb_error("usb_get_string_simple", ret); return INT2NUM(ret); }
/* USB::DevHandle#usb_get_driver_np(interface, name) */ static VALUE rusb_get_driver_np( VALUE v, VALUE vinterface, VALUE vname) { usb_dev_handle *p = get_usb_devhandle(v); int interface = NUM2INT(vinterface); char *name; int namelen; int ret; StringValue(vname); rb_str_modify(vname); name = RSTRING_PTR(vname); namelen = RSTRING_LEN(vname); ret = usb_get_driver_np(p, interface, name, namelen); check_usb_error("usb_get_driver_np", ret); return Qnil; }
static VALUE _receive(int rflags, int argc, VALUE *argv, VALUE self) { struct posix_mq *mq = get(self, 1); struct rw_args x; VALUE buffer, timeout; struct timespec expire; if (mq->attr.mq_msgsize < 0) { if (mq_getattr(mq->des, &mq->attr) < 0) rb_sys_fail("mq_getattr"); } rb_scan_args(argc, argv, "02", &buffer, &timeout); x.timeout = convert_timeout(&expire, timeout); if (NIL_P(buffer)) { buffer = rb_str_new(0, mq->attr.mq_msgsize); } else { StringValue(buffer); rb_str_modify(buffer); rb_str_resize(buffer, mq->attr.mq_msgsize); } OBJ_TAINT(buffer); x.msg_ptr = RSTRING_PTR(buffer); x.msg_len = (size_t)mq->attr.mq_msgsize; x.des = mq->des; retry: WITHOUT_GVL(xrecv, &x, RUBY_UBF_IO, 0); if (x.received < 0) { if (errno == EINTR) goto retry; if (errno == EAGAIN && (rflags & PMQ_TRY)) return Qnil; rb_sys_fail("mq_receive"); } rb_str_set_len(buffer, x.received); if (rflags & PMQ_WANTARRAY) return rb_ary_new3(2, buffer, UINT2NUM(x.msg_prio)); return buffer; }
/* USB::DevHandle#usb_interrupt_read(endpoint, bytes, timeout) */ static VALUE rusb_interrupt_read( VALUE v, VALUE vep, VALUE vbytes, VALUE vtimeout) { usb_dev_handle *p = get_usb_devhandle(v); int ep = NUM2INT(vep); int timeout = NUM2INT(vtimeout); char *bytes; int size; int ret; StringValue(vbytes); rb_str_modify(vbytes); bytes = RSTRING_PTR(vbytes); size = RSTRING_LEN(vbytes); ret = usb_interrupt_read(p, ep, bytes, size, timeout); check_usb_error("usb_interrupt_read", ret); return INT2NUM(ret); }
VALUE rb_str_vcatf(VALUE str, const char *fmt, va_list ap) { rb_printf_buffer f; VALUE klass; StringValue(str); rb_str_modify(str); f._flags = __SWR | __SSTR; f._bf._size = 0; f._w = rb_str_capacity(str); f._bf._base = (unsigned char *)str; f._p = (unsigned char *)RSTRING_END(str); klass = RBASIC(str)->klass; RBASIC(str)->klass = 0; f.vwrite = ruby__sfvwrite; BSD_vfprintf(&f, fmt, ap); RBASIC(str)->klass = klass; rb_str_resize(str, (char *)f._p - RSTRING_PTR(str)); return str; }
/* USB::DevHandle#usb_get_descriptor_by_endpoint(endpoint, type, index, buf) */ static VALUE rusb_get_descriptor_by_endpoint( VALUE v, VALUE vep, VALUE vtype, VALUE vindex, VALUE vbuf) { usb_dev_handle *p = get_usb_devhandle(v); int ep = NUM2INT(vep); int type = NUM2INT(vtype); int index = NUM2INT(vindex); char *buf; int buflen; int ret; StringValue(vbuf); rb_str_modify(vbuf); buf = RSTRING_PTR(vbuf); buflen = RSTRING_LEN(vbuf); ret = usb_get_descriptor_by_endpoint(p, ep, type, index, buf, buflen); check_usb_error("usb_get_descriptor_by_endpoint", ret); return INT2NUM(ret); }
/* * call-seq: * str.to_c -> complex * * Returns a complex which denotes the string form. The parser * ignores leading whitespaces and trailing garbage. Any digit * sequences can be separated by an underscore. Returns zero for null * or garbage string. * * '9'.to_c #=> (9+0i) * '2.5'.to_c #=> (2.5+0i) * '2.5/1'.to_c #=> ((5/2)+0i) * '-3/2'.to_c #=> ((-3/2)+0i) * '-i'.to_c #=> (0-1i) * '45i'.to_c #=> (0+45i) * '3-4i'.to_c #=> (3-4i) * '-4e2-4e-2i'.to_c #=> (-400.0-0.04i) * '-0.0-0.0i'.to_c #=> (-0.0-0.0i) * '1/2+3/4i'.to_c #=> ((1/2)+(3/4)*i) * 'ruby'.to_c #=> (0+0i) * * See Kernel.Complex. */ static VALUE string_to_c(VALUE self) { char *s; VALUE num; rb_must_asciicompat(self); s = RSTRING_PTR(self); if (s && s[RSTRING_LEN(self)]) { rb_str_modify(self); s = RSTRING_PTR(self); s[RSTRING_LEN(self)] = '\0'; } if (!s) s = (char *)""; (void)parse_comp(s, 0, &num); return num; }
static VALUE rb_utf_chomp_newlines(VALUE str) { char *begin = RSTRING(str)->ptr; char *end = begin + RSTRING(str)->len; char *last = end; while (last > begin) { char *last_but_one = utf_find_prev(begin, last); if (last == NULL || !unichar_isnewline(utf_char(last_but_one))) break; last = last_but_one; } if (last == end) return Qnil; rb_str_modify(str); RSTRING(str)->len -= end - last; *last = '\0'; return str; }
static VALUE ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) { SSL *ssl; int ilen, nread = 0; VALUE len, str; rb_io_t *fptr; rb_scan_args(argc, argv, "11", &len, &str); ilen = NUM2INT(len); if(NIL_P(str)) { str = rb_bstr_new(); } else{ StringValue(str); rb_str_modify(str); str = rb_str_bstr(str); } rb_bstr_resize(str, ilen); if(ilen == 0) return str; Data_Get_Struct(self, SSL, ssl); GetOpenFile(ossl_ssl_get_io(self), fptr); if (ssl) { if(!nonblock && SSL_pending(ssl) <= 0) rb_thread_wait_fd(FPTR_TO_FD(fptr)); for (;;){ nread = SSL_read(ssl, rb_bstr_bytes(str), rb_bstr_length(str)); switch(ssl_get_error(ssl, nread)){ case SSL_ERROR_NONE: goto end; case SSL_ERROR_ZERO_RETURN: rb_eof_error(); case SSL_ERROR_WANT_WRITE: write_would_block(nonblock); rb_io_wait_writable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_WANT_READ: read_would_block(nonblock); rb_io_wait_readable(FPTR_TO_FD(fptr)); continue; case SSL_ERROR_SYSCALL: if(ERR_peek_error() == 0 && nread == 0) rb_eof_error(); rb_sys_fail(0); default: ossl_raise(eSSLError, "SSL_read:"); } } } else { ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread"); rb_warning("SSL session is not started yet."); return rb_funcall(ossl_ssl_get_io(self), meth, 2, len, str); } end: rb_bstr_resize(str, nread); OBJ_TAINT(str); return str; }
VALUE image_open(VALUE self, VALUE filename_location, VALUE disk_type_flag) { char * filename; int dtype; struct tsk4r_img_wrapper * ptr; Data_Get_Struct(self, struct tsk4r_img_wrapper, ptr); VALUE img_size; VALUE img_sector_size; VALUE description = Qnil; VALUE name = Qnil; dtype = FIX2ULONG(disk_type_flag); TSK_IMG_TYPE_ENUM * type_flag_num = get_img_flag(disk_type_flag); if (rb_obj_is_kind_of(filename_location, rb_cString)) { fprintf(stdout, "opening %s. (flag=%d)\n", StringValuePtr(filename_location), dtype); rb_str_modify(filename_location); filename=StringValuePtr(filename_location); ptr->image = tsk_img_open_sing(filename, (TSK_IMG_TYPE_ENUM)type_flag_num, 0); // 0=default sector size if (ptr->image == NULL) rb_warn("unable to open image %s.\n", StringValuePtr(filename_location)); } else if (rb_obj_is_kind_of(filename_location, rb_cArray)) { long i; typedef TSK_TCHAR * split_list; split_list images[255]; // to do: make array length reflect list's length for (i=0; i < RARRAY_LEN(filename_location); i++) { VALUE rstring = rb_ary_entry(filename_location, i); images[i] = StringValuePtr(rstring); } int count = (int)RARRAY_LEN(filename_location); ptr->image = tsk_img_open(count, (const TSK_TCHAR **)images, (TSK_IMG_TYPE_ENUM)type_flag_num, 0); // 0=default sector size VALUE arr_to_s = rb_funcall(filename_location, rb_intern("to_s"), 0, NULL); if (ptr->image == NULL) rb_warn("unable to open images %s.\n", StringValuePtr(arr_to_s)); } else { rb_raise(rb_eArgError, "Arg1 should be String or Array of strings."); } if (ptr->image == NULL) { rb_funcall(self, rb_intern("taint"), 0, NULL); return Qnil; } else { TSK_IMG_INFO *image = ptr->image; img_size = LONG2NUM(image->size); img_sector_size = INT2NUM((int)image->sector_size); TSK_IMG_TYPE_ENUM typenum = image->itype; description = image_type_to_desc(self, INT2NUM(typenum)); name = image_type_to_name(self, INT2NUM(typenum)); rb_iv_set(self, "@size", img_size); rb_iv_set(self, "@sector_size", img_sector_size); rb_iv_set(self, "@type", INT2NUM((int)typenum)); rb_iv_set(self, "@description", description); rb_iv_set(self, "@name", name); return self; } }
VALUE CRbWin32API::call(int argc, VALUE * argv, VALUE obj) { struct { u32 params[16]; } param; VALUE obj_proc = rb_iv_get(obj, "__proc__"); VALUE obj_import = rb_iv_get(obj, "__import__"); VALUE obj_export = rb_iv_get(obj, "__export__"); FARPROC ApiFunction = (FARPROC)rb_num2ulong(obj_proc); VALUE args; int items = rb_scan_args(argc, argv, "0*", &args); int nimport = RARRAY_LEN(obj_import); if (items != nimport) rb_raise(rb_eSinError, "wrong number of parameters: expected %d, got %d", nimport, items); for (int i = 0; i < nimport; ++i) { u32 lParam = 0; switch (FIX2INT(rb_ary_entry(obj_import, i))) { VALUE str; case _T_NUMBER: case _T_INTEGER: default: lParam = rb_num2ulong(rb_ary_entry(args, i)); break; case _T_POINTER: str = rb_ary_entry(args, i); if (NIL_P(str)) { lParam = 0; } else if (FIXNUM_P(str)) { lParam = rb_num2ulong(str); } else { rb_string_value(&str); rb_str_modify(str); lParam = (u32)rb_string_value_ptr(&str); } break; } param.params[i] = lParam; } u32 retval; __try { __asm { mov ebx, esp sub esp, 40h mov ecx, 10h lea esi, [param] mov edi, esp rep movs dword ptr es:[edi], dword ptr [esi] call dword ptr [ApiFunction] mov esp, ebx mov dword ptr [retval], eax } } __except(EXCEPTION_EXECUTE_HANDLER) { rb_raise(rb_eSinError, "Api Crashed..."); } switch (FIX2INT(obj_export)) { case _T_NUMBER: case _T_INTEGER: return rb_int2inum(retval); case _T_POINTER: return (retval ? rb_str_new2((char *)retval) : Qnil); case _T_VOID: default: return INT2FIX(0); } }
VALUE rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_name, VALUE result) { size_t size = 0, wpath_len = 0, wdir_len = 0, whome_len = 0; size_t buffer_len = 0; char *fullpath = NULL; wchar_t *wfullpath = NULL, *wpath = NULL, *wpath_pos = NULL; wchar_t *wdir = NULL, *wdir_pos = NULL; wchar_t *whome = NULL, *buffer = NULL, *buffer_pos = NULL; UINT path_cp, cp; VALUE path = fname, dir = dname; wchar_t wfullpath_buffer[PATH_BUFFER_SIZE]; wchar_t path_drive = L'\0', dir_drive = L'\0'; int ignore_dir = 0; rb_encoding *path_encoding; int tainted = 0; /* tainted if path is tainted */ tainted = OBJ_TAINTED(path); /* get path encoding */ if (NIL_P(dir)) { path_encoding = rb_enc_get(path); } else { path_encoding = rb_enc_check(path, dir); } cp = path_cp = code_page(path_encoding); /* workaround invalid codepage */ if (path_cp == INVALID_CODE_PAGE) { cp = CP_UTF8; if (!NIL_P(path)) { path = fix_string_encoding(path, path_encoding); } } /* convert char * to wchar_t */ convert_mb_to_wchar(path, &wpath, &wpath_pos, &wpath_len, cp); /* determine if we need the user's home directory */ /* expand '~' only if NOT rb_file_absolute_path() where `abs_mode` is 1 */ if (abs_mode == 0 && wpath_len > 0 && wpath_pos[0] == L'~' && (wpath_len == 1 || IS_DIR_SEPARATOR_P(wpath_pos[1]))) { /* tainted if expanding '~' */ tainted = 1; whome = home_dir(); if (whome == NULL) { xfree(wpath); rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'"); } whome_len = wcslen(whome); if (PathIsRelativeW(whome) && !(whome_len >= 2 && IS_DIR_UNC_P(whome))) { xfree(wpath); rb_raise(rb_eArgError, "non-absolute home"); } /* use filesystem encoding if expanding home dir */ path_encoding = rb_filesystem_encoding(); cp = path_cp = system_code_page(); /* ignores dir since we are expading home */ ignore_dir = 1; /* exclude ~ from the result */ wpath_pos++; wpath_len--; /* exclude separator if present */ if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { wpath_pos++; wpath_len--; } } else if (wpath_len >= 2 && wpath_pos[1] == L':') { if (wpath_len >= 3 && IS_DIR_SEPARATOR_P(wpath_pos[2])) { /* ignore dir since path contains a drive letter and a root slash */ ignore_dir = 1; } else { /* determine if we ignore dir or not later */ path_drive = wpath_pos[0]; } } else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] == L'~') { result = get_user_from_path(&wpath_pos, 1, cp, path_cp, path_encoding); if (wpath) xfree(wpath); rb_raise(rb_eArgError, "can't find user %s", StringValuePtr(result)); } /* convert dir */ if (!ignore_dir && !NIL_P(dir)) { /* fix string encoding */ if (path_cp == INVALID_CODE_PAGE) { dir = fix_string_encoding(dir, path_encoding); } /* convert char * to wchar_t */ convert_mb_to_wchar(dir, &wdir, &wdir_pos, &wdir_len, cp); if (abs_mode == 0 && wdir_len > 0 && wdir_pos[0] == L'~' && (wdir_len == 1 || IS_DIR_SEPARATOR_P(wdir_pos[1]))) { /* tainted if expanding '~' */ tainted = 1; whome = home_dir(); if (whome == NULL) { xfree(wpath); xfree(wdir); rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'"); } whome_len = wcslen(whome); if (PathIsRelativeW(whome) && !(whome_len >= 2 && IS_DIR_UNC_P(whome))) { xfree(wpath); xfree(wdir); rb_raise(rb_eArgError, "non-absolute home"); } /* exclude ~ from the result */ wdir_pos++; wdir_len--; /* exclude separator if present */ if (wdir_len && IS_DIR_SEPARATOR_P(wdir_pos[0])) { wdir_pos++; wdir_len--; } } else if (wdir_len >= 2 && wdir[1] == L':') { dir_drive = wdir[0]; if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { wdir_len = 2; } } else if (wdir_len >= 2 && IS_DIR_UNC_P(wdir)) { /* UNC path */ if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { /* cut the UNC path tail to '//host/share' */ size_t separators = 0; size_t pos = 2; while (pos < wdir_len && separators < 2) { if (IS_DIR_SEPARATOR_P(wdir[pos])) { separators++; } pos++; } if (separators == 2) wdir_len = pos - 1; } } else if (abs_mode == 0 && wdir_len >= 2 && wdir_pos[0] == L'~') { result = get_user_from_path(&wdir_pos, 1, cp, path_cp, path_encoding); if (wpath) xfree(wpath); if (wdir) xfree(wdir); rb_raise(rb_eArgError, "can't find user %s", StringValuePtr(result)); } } /* determine if we ignore dir or not */ if (!ignore_dir && path_drive && dir_drive) { if (towupper(path_drive) == towupper(dir_drive)) { /* exclude path drive letter to use dir */ wpath_pos += 2; wpath_len -= 2; } else { /* ignore dir since path drive is different from dir drive */ ignore_dir = 1; wdir_len = 0; } } if (!ignore_dir && wpath_len >= 2 && IS_DIR_UNC_P(wpath)) { /* ignore dir since path has UNC root */ ignore_dir = 1; wdir_len = 0; } else if (!ignore_dir && wpath_len >= 1 && IS_DIR_SEPARATOR_P(wpath[0]) && !dir_drive && !(wdir_len >= 2 && IS_DIR_UNC_P(wdir))) { /* ignore dir since path has root slash and dir doesn't have drive or UNC root */ ignore_dir = 1; wdir_len = 0; } buffer_len = wpath_len + 1 + wdir_len + 1 + whome_len + 1; buffer = buffer_pos = (wchar_t *)xmalloc((buffer_len + 1) * sizeof(wchar_t)); /* add home */ if (whome_len) { wcsncpy(buffer_pos, whome, whome_len); buffer_pos += whome_len; } /* Add separator if required */ if (whome_len && wcsrchr(L"\\/:", buffer_pos[-1]) == NULL) { buffer_pos[0] = L'\\'; buffer_pos++; } if (wdir_len) { /* tainted if dir is used and dir is tainted */ if (!tainted && OBJ_TAINTED(dir)) tainted = 1; wcsncpy(buffer_pos, wdir_pos, wdir_len); buffer_pos += wdir_len; } /* add separator if required */ if (wdir_len && wcsrchr(L"\\/:", buffer_pos[-1]) == NULL) { buffer_pos[0] = L'\\'; buffer_pos++; } /* now deal with path */ if (wpath_len) { wcsncpy(buffer_pos, wpath_pos, wpath_len); buffer_pos += wpath_len; } /* GetFullPathNameW requires at least "." to determine current directory */ if (wpath_len == 0) { buffer_pos[0] = L'.'; buffer_pos++; } /* Ensure buffer is NULL terminated */ buffer_pos[0] = L'\0'; /* tainted if path is relative */ if (!tainted && PathIsRelativeW(buffer) && !(buffer_len >= 2 && IS_DIR_UNC_P(buffer))) tainted = 1; /* FIXME: Make this more robust */ /* Determine require buffer size */ size = GetFullPathNameW(buffer, PATH_BUFFER_SIZE, wfullpath_buffer, NULL); if (size > PATH_BUFFER_SIZE) { /* allocate more memory than alloted originally by PATH_BUFFER_SIZE */ wfullpath = (wchar_t *)xmalloc(size * sizeof(wchar_t)); size = GetFullPathNameW(buffer, size, wfullpath, NULL); } else { wfullpath = wfullpath_buffer; } /* Remove any trailing slashes */ if (IS_DIR_SEPARATOR_P(wfullpath[size - 1]) && wfullpath[size - 2] != L':' && !(size == 2 && IS_DIR_UNC_P(wfullpath))) { size -= 1; wfullpath[size] = L'\0'; } /* Remove any trailing dot */ if (wfullpath[size - 1] == L'.') { size -= 1; wfullpath[size] = L'\0'; } /* removes trailing invalid ':$DATA' */ size = remove_invalid_alternative_data(wfullpath, size); /* Replace the trailing path to long name */ if (long_name) size = replace_to_long_name(&wfullpath, size, (wfullpath != wfullpath_buffer)); /* sanitize backslashes with forwardslashes */ replace_wchar(wfullpath, L'\\', L'/'); /* convert to char * */ size = WideCharToMultiByte(cp, 0, wfullpath, size, NULL, 0, NULL, NULL); if (size > (size_t)RSTRING_LEN(result)) { rb_str_modify(result); rb_str_resize(result, size); } WideCharToMultiByte(cp, 0, wfullpath, size, RSTRING_PTR(result), size, NULL, NULL); rb_str_set_len(result, size); /* convert to VALUE and set the path encoding */ if (path_cp == INVALID_CODE_PAGE) { VALUE tmp; size_t len; rb_enc_associate(result, rb_utf8_encoding()); ENC_CODERANGE_CLEAR(result); tmp = rb_str_encode(result, rb_enc_from_encoding(path_encoding), 0, Qnil); len = RSTRING_LEN(tmp); rb_str_modify(result); rb_str_resize(result, len); memcpy(RSTRING_PTR(result), RSTRING_PTR(tmp), len); rb_str_resize(tmp, 0); } rb_enc_associate(result, path_encoding); ENC_CODERANGE_CLEAR(result); /* makes the result object tainted if expanding tainted strings or returning modified path */ if (tainted) OBJ_TAINT(result); /* TODO: better cleanup */ if (buffer) xfree(buffer); if (wpath) xfree(wpath); if (wdir) xfree(wdir); if (whome) xfree(whome); if (wfullpath && wfullpath != wfullpath_buffer) xfree(wfullpath); if (fullpath) xfree(fullpath); return result; }
/* * call-seq: * Win32::API#call(arg1, arg2, ...) * * Calls the function pointer with the given arguments (if any). Note that, * while this method will catch some prototype mismatches (raising a TypeError * in the process), it is not fulproof. It is ultimately your job to make * sure the arguments match the +prototype+ specified in the constructor. * * For convenience, nil is converted to NULL, true is converted to TRUE (1) * and false is converted to FALSE (0). */ static VALUE api_call(int argc, VALUE* argv, VALUE self){ VALUE v_proto, v_args, v_arg, v_return; Win32API* ptr; unsigned long return_value; int i = 0; int len; struct{ unsigned long params[20]; } param; Data_Get_Struct(self, Win32API, ptr); rb_scan_args(argc, argv, "0*", &v_args); v_proto = rb_iv_get(self, "@prototype"); // For void prototypes, allow either no args or an explicit nil if(RARRAY_LEN(v_proto) != RARRAY_LEN(v_args)){ char* c = StringValuePtr(RARRAY_PTR(v_proto)[0]); if(!strcmp(c, "V")){ rb_ary_push(v_args, Qnil); } else{ rb_raise(rb_eArgError, "wrong number of parameters: expected %d, got %d", RARRAY_LEN(v_proto), RARRAY_LEN(v_args) ); } } len = RARRAY_LEN(v_proto); for(i = 0; i < len; i++){ v_arg = RARRAY_PTR(v_args)[i]; // Convert nil to NULL. Otherwise convert as appropriate. if(NIL_P(v_arg)) param.params[i] = (unsigned long)NULL; else if(v_arg == Qtrue) param.params[i] = TRUE; else if(v_arg == Qfalse) param.params[i] = FALSE; else switch(ptr->prototype[i]){ case _T_LONG: param.params[i] = NUM2ULONG(v_arg); break; case _T_INTEGER: param.params[i] = NUM2INT(v_arg); break; case _T_POINTER: if(FIXNUM_P(v_arg)){ param.params[i] = NUM2ULONG(v_arg); } else{ StringValue(v_arg); rb_str_modify(v_arg); param.params[i] = (unsigned long)StringValuePtr(v_arg); } break; case _T_CALLBACK: ActiveCallback = v_arg; v_proto = rb_iv_get(ActiveCallback, "@prototype"); param.params[i] = (LPARAM)NUM2ULONG(rb_iv_get(ActiveCallback, "@address"));; break; case _T_STRING: param.params[i] = (unsigned long)RSTRING_PTR(v_arg); break; default: param.params[i] = NUM2ULONG(v_arg); } } /* Call the function, get the return value */ return_value = ptr->function(param); /* Return the appropriate type based on the return type specified * in the constructor. */ switch(ptr->return_type){ case _T_INTEGER: v_return = INT2NUM(return_value); break; case _T_LONG: v_return = ULONG2NUM(return_value); break; case _T_VOID: v_return = Qnil; break; case _T_POINTER: if(!return_value){ v_return = Qnil; } else{ VALUE v_efunc = rb_iv_get(self, "@effective_function_name"); char* efunc = RSTRING_PTR(v_efunc); if(efunc[strlen(efunc)-1] == 'W'){ v_return = rb_str_new( (TCHAR*)return_value, wcslen((wchar_t*)return_value)*2 ); } else{ v_return = rb_str_new2((TCHAR*)return_value); } } break; case _T_STRING: { VALUE v_efunc = rb_iv_get(self, "@effective_function_name"); char* efunc = RSTRING_PTR(v_efunc); if(efunc[strlen(efunc)-1] == 'W'){ v_return = rb_str_new( (TCHAR*)return_value, wcslen((wchar_t*)return_value)*2 ); } else{ v_return = rb_str_new2((TCHAR*)return_value); } } break; default: v_return = INT2NUM(0); } return v_return; }
DWORD CallbackFunction(CALLPARAM param, VALUE callback) { VALUE v_proto, v_return, v_proc, v_retval; VALUE argv[20]; int i, argc; char *a_proto; char *a_return; if(callback && !NIL_P(callback)){ v_proto = rb_iv_get(callback, "@prototype"); a_proto = RSTRING_PTR(v_proto); v_return = rb_iv_get(callback, "@return_type"); a_return = RSTRING_PTR(v_return); v_proc = rb_iv_get(callback, "@function"); argc = RSTRING_LEN(v_proto); for(i=0; i < RSTRING_LEN(v_proto); i++){ argv[i] = Qnil; switch(a_proto[i]){ case 'L': argv[i] = ULONG2NUM(param.params[i]); break; case 'P': if(param.params[i]) argv[i] = rb_str_new2((char *)param.params[i]); break; case 'I': argv[i] = INT2NUM(param.params[i]); break; default: rb_raise(cAPIProtoError, "Illegal prototype '%s'", a_proto[i]); } } v_retval = rb_funcall2(v_proc, rb_intern("call"), argc, argv); /* Handle true and false explicitly, as some CALLBACK functions * require TRUE or FALSE to break out of loops, etc. */ if(v_retval == Qtrue) return TRUE; else if(v_retval == Qfalse) return FALSE; switch (*a_return) { case 'I': return NUM2INT(v_retval); break; case 'L': return NUM2ULONG(v_retval); break; case 'S': return (unsigned long)RSTRING_PTR(v_retval); break; case 'P': if(NIL_P(v_retval)){ return 0; } else if(FIXNUM_P(v_retval)){ return NUM2ULONG(v_retval); } else{ StringValue(v_retval); rb_str_modify(v_retval); return (unsigned long)StringValuePtr(v_retval); } break; } } return 0; }