[CRT]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Mon, 21 Jun 2010 19:57:36 +0000 (19:57 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Mon, 21 Jun 2010 19:57:36 +0000 (19:57 +0000)
- Stubplement _controlfp_s, rand_s
- Implement _invalid_parameter, _get_invalid_parameter_handler, _set_invalid_parameter_handler
- Implement memmove_s, strncpy_s
- sync heap.c with wine
Patch by Samuel Serapion

svn path=/trunk/; revision=47822

reactos/lib/sdk/crt/crt.rbuild
reactos/lib/sdk/crt/float/i386/cntrlfp.c
reactos/lib/sdk/crt/math/rand.c
reactos/lib/sdk/crt/misc/stubs.c
reactos/lib/sdk/crt/stdlib/errno.c
reactos/lib/sdk/crt/wine/heap.c

index 0fd49d1..7b4bc6f 100644 (file)
                <file>gcvt.c</file>
                <file>getenv.c</file>
                <file>makepath.c</file>
-               <file>malloc.c</file>
                <file>mbtowc.c</file>
                <file>mbstowcs.c</file>
                <file>obsol.c</file>
index 2cc46d8..75d5c0a 100644 (file)
@@ -104,3 +104,25 @@ unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
 
   return flags;
 }
+
+/*********************************************************************
+ *              _controlfp_s (MSVCRT.@)
+ */
+int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
+{
+#ifdef __i386__
+    unsigned int flags;
+
+    FIXME("(%p %u %u) semi-stub\n", cur, newval, mask);
+
+    flags = _control87( newval, mask & ~_EM_DENORMAL );
+
+    if(cur)
+        *cur = flags;
+
+    return 0;
+#else
+    FIXME(":Not Implemented!\n");
+    return 0;
+#endif
+}
index f788ecf..4d560a2 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
 #include <precomp.h>
-
+//#include <Ntsecapi.h>
 #include <internal/tls.h>
 
 /*
@@ -25,3 +25,18 @@ srand(unsigned int seed)
 
   ThreadData->tnext = (ULONGLONG)seed;
 }
+
+ /*********************************************************************
+  *              rand_s (MSVCRT.@)
+  */
+int CDECL rand_s(unsigned int *pval)
+{
+#if 0
+    if (!pval || !RtlGenRandom(pval, sizeof(*pval)))
+    {
+        *_errno() = EINVAL;
+        return EINVAL;
+    }
+#endif
+    return 0;
+}
index 00f4a2b..7eac2b0 100644 (file)
@@ -15,11 +15,6 @@ void MSVCRT_I10_OUTPUT(void)
   /* FIXME: This is probably data, not a function */
 }
 
-void __p__amblksiz(void)
-{
-   FIXME("__p__amblksiz stub\n");
-}
-
 void __fileinfo(void)
 {
    FIXME("__fileinfo stub\n");
index 3a8d76e..6cbd20a 100644 (file)
@@ -8,8 +8,11 @@
  */
 #include <precomp.h>
 #include "doserrmap.h"
+#include <errno.h>
 #include <internal/wine/msvcrt.h>
 
+static _invalid_parameter_handler invalid_parameter_handler = NULL;
+
 /*
  * @implemented
  */
@@ -113,4 +116,36 @@ void CDECL _seterrormode(int mode)
     SetErrorMode( mode );
 }
 
+/******************************************************************************
+ *             _invalid_parameter (MSVCRT.@)
+ */
+void __cdecl _invalid_parameter(const wchar_t *expr, const wchar_t *func,
+                                       const wchar_t *file, unsigned int line, uintptr_t arg)
+{
+    if (invalid_parameter_handler) invalid_parameter_handler( expr, func, file, line, arg );
+    else
+    {
+        ERR( "%s:%u %s: %s %lx\n", debugstr_w(file), line, debugstr_w(func), debugstr_w(expr), arg );
+        RaiseException( STATUS_INVALID_CRUNTIME_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, NULL );
+    }
+}
+
+/* _get_invalid_parameter_handler - not exported in native msvcrt, added in msvcr80 */
+_invalid_parameter_handler CDECL _get_invalid_parameter_handler(void)
+{
+    TRACE("\n");
+    return invalid_parameter_handler;
+}
+
+/* _set_invalid_parameter_handler - not exproted in native msvcrt, added in msvcr80 */
+_invalid_parameter_handler CDECL _set_invalid_parameter_handler(
+        _invalid_parameter_handler handler)
+{
+    _invalid_parameter_handler old = invalid_parameter_handler;
+
+    TRACE("(%p)\n", handler);
+
+    invalid_parameter_handler = handler;
+    return old;
+}
 /* EOF */
index daabff8..0897370 100644 (file)
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Note: Win32 heap operations are MT safe. We only lock the new
  *       handler and non atomic heap operations
  */
 
 #include <precomp.h>
+#include <malloc.h>
 
 /* MT */
 #define LOCK_HEAP   _mlock( _HEAP_LOCK )
 
 /* _aligned */
 #define SAVED_PTR(x) ((void *)((DWORD_PTR)((char *)x - sizeof(void *)) & \
-                                ~(sizeof(void *) - 1)))
+                               ~(sizeof(void *) - 1)))
 #define ALIGN_PTR(ptr, alignment, offset) ((void *) \
     ((((DWORD_PTR)((char *)ptr + alignment + sizeof(void *) + offset)) & \
       ~(alignment - 1)) - offset))
 
-typedef void (*MSVCRT_new_handler_func)(unsigned long size);
+typedef void (*MSVCRT_new_handler_func)(size_t size);
 
 static MSVCRT_new_handler_func MSVCRT_new_handler;
 static int MSVCRT_new_mode;
 
+/* FIXME - According to documentation it should be 8*1024, at runtime it returns 16 */ 
+static unsigned int MSVCRT_amblksiz = 16;
 /* FIXME - According to documentation it should be 480 bytes, at runtime default is 0 */
 static size_t MSVCRT_sbh_threshold = 0;
 
 /*********************************************************************
  *             ??2@YAPAXI@Z (MSVCRT.@)
  */
-void* MSVCRT_operator_new(unsigned long size)
+void* CDECL MSVCRT_operator_new(size_t size)
 {
-  void *retval = malloc(size);
+  void *retval = HeapAlloc(GetProcessHeap(), 0, size);
   TRACE("(%ld) returning %p\n", size, retval);
+  if(retval) return retval;
   LOCK_HEAP;
-  if(!retval && MSVCRT_new_handler)
+  if(MSVCRT_new_handler)
     (*MSVCRT_new_handler)(size);
   UNLOCK_HEAP;
   return retval;
 }
 
+
+/*********************************************************************
+ *             ??2@YAPAXIHPBDH@Z (MSVCRT.@)
+ */
+void* CDECL MSVCRT_operator_new_dbg(size_t size, int type, const char *file, int line)
+{
+    return MSVCRT_operator_new( size );
+}
+
+
 /*********************************************************************
  *             ??3@YAXPAX@Z (MSVCRT.@)
  */
-void MSVCRT_operator_delete(void *mem)
+void CDECL MSVCRT_operator_delete(void *mem)
 {
   TRACE("(%p)\n", mem);
-  free(mem);
+  HeapFree(GetProcessHeap(), 0, mem);
 }
 
 
 /*********************************************************************
  *             ?_query_new_handler@@YAP6AHI@ZXZ (MSVCRT.@)
  */
-MSVCRT_new_handler_func MSVCRT__query_new_handler(void)
+MSVCRT_new_handler_func CDECL MSVCRT__query_new_handler(void)
 {
   return MSVCRT_new_handler;
 }
@@ -78,7 +92,7 @@ MSVCRT_new_handler_func MSVCRT__query_new_handler(void)
 /*********************************************************************
  *             ?_query_new_mode@@YAHXZ (MSVCRT.@)
  */
-int MSVCRT__query_new_mode(void)
+int CDECL MSVCRT__query_new_mode(void)
 {
   return MSVCRT_new_mode;
 }
@@ -86,7 +100,7 @@ int MSVCRT__query_new_mode(void)
 /*********************************************************************
  *             ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z (MSVCRT.@)
  */
-MSVCRT_new_handler_func MSVCRT__set_new_handler(MSVCRT_new_handler_func func)
+MSVCRT_new_handler_func CDECL MSVCRT__set_new_handler(MSVCRT_new_handler_func func)
 {
   MSVCRT_new_handler_func old_handler;
   LOCK_HEAP;
@@ -99,7 +113,7 @@ MSVCRT_new_handler_func MSVCRT__set_new_handler(MSVCRT_new_handler_func func)
 /*********************************************************************
  *             ?set_new_handler@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
  */
-MSVCRT_new_handler_func MSVCRT_set_new_handler(void *func)
+MSVCRT_new_handler_func CDECL MSVCRT_set_new_handler(void *func)
 {
   TRACE("(%p)\n",func);
   MSVCRT__set_new_handler(NULL);
@@ -109,7 +123,7 @@ MSVCRT_new_handler_func MSVCRT_set_new_handler(void *func)
 /*********************************************************************
  *             ?_set_new_mode@@YAHH@Z (MSVCRT.@)
  */
-int MSVCRT__set_new_mode(int mode)
+int CDECL MSVCRT__set_new_mode(int mode)
 {
   int old_mode;
   LOCK_HEAP;
@@ -119,45 +133,216 @@ int MSVCRT__set_new_mode(int mode)
   return old_mode;
 }
 
-int CDECL _callnewh(unsigned long size)
+/*********************************************************************
+ *             _callnewh (MSVCRT.@)
+ */
+int CDECL _callnewh(size_t size)
 {
-    if(MSVCRT_new_handler)
-        (*MSVCRT_new_handler)(size);
-    return 0;
+  if(MSVCRT_new_handler)
+    (*MSVCRT_new_handler)(size);
+  return 0;
 }
 
 /*********************************************************************
- *              _get_sbh_threshold (MSVCRT.@)
+ *             _expand (MSVCRT.@)
  */
-size_t CDECL _get_sbh_threshold(void)
+void* CDECL _expand(void* mem, size_t size)
 {
-    return MSVCRT_sbh_threshold;
+  return HeapReAlloc(GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, mem, size);
 }
 
 /*********************************************************************
- *              _set_sbh_threshold (MSVCRT.@)
+ *             _heapchk (MSVCRT.@)
  */
-int CDECL _set_sbh_threshold(size_t threshold)
+int CDECL _heapchk(void)
 {
-    if(threshold > 1016)
-        return 0;
-    else
-        MSVCRT_sbh_threshold = threshold;
-    return 1;
+  if (!HeapValidate( GetProcessHeap(), 0, NULL))
+  {
+    __set_errno(GetLastError());
+    return _HEAPBADNODE;
+  }
+  return _HEAPOK;
+}
+
+/*********************************************************************
+ *             _heapmin (MSVCRT.@)
+ */
+int CDECL _heapmin(void)
+{
+  if (!HeapCompact( GetProcessHeap(), 0 ))
+  {
+    if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+      __set_errno(GetLastError());
+    return -1;
+  }
+  return 0;
+}
+
+/*********************************************************************
+ *             _heapwalk (MSVCRT.@)
+ */
+int CDECL _heapwalk(_HEAPINFO* next)
+{
+  PROCESS_HEAP_ENTRY phe;
+
+  LOCK_HEAP;
+  phe.lpData = next->_pentry;
+  phe.cbData = next->_size;
+  phe.wFlags = next->_useflag == _USEDENTRY ? PROCESS_HEAP_ENTRY_BUSY : 0;
+
+  if (phe.lpData && phe.wFlags & PROCESS_HEAP_ENTRY_BUSY &&
+      !HeapValidate( GetProcessHeap(), 0, phe.lpData ))
+  {
+    UNLOCK_HEAP;
+   __set_errno(GetLastError());
+    return _HEAPBADNODE;
+  }
+
+  do
+  {
+    if (!HeapWalk( GetProcessHeap(), &phe ))
+    {
+      UNLOCK_HEAP;
+      if (GetLastError() == ERROR_NO_MORE_ITEMS)
+         return _HEAPEND;
+      __set_errno(GetLastError());
+      if (!phe.lpData)
+        return _HEAPBADBEGIN;
+      return _HEAPBADNODE;
+    }
+  } while (phe.wFlags & (PROCESS_HEAP_REGION|PROCESS_HEAP_UNCOMMITTED_RANGE));
+
+  UNLOCK_HEAP;
+  next->_pentry = phe.lpData;
+  next->_size = phe.cbData;
+  next->_useflag = phe.wFlags & PROCESS_HEAP_ENTRY_BUSY ? _USEDENTRY : _FREEENTRY;
+  return _HEAPOK;
+}
+
+/*********************************************************************
+ *             _heapset (MSVCRT.@)
+ */
+int CDECL _heapset(unsigned int value)
+{
+  int retval;
+  _HEAPINFO heap;
+
+  memset( &heap, 0, sizeof(heap) );
+  LOCK_HEAP;
+  while ((retval = _heapwalk(&heap)) == _HEAPOK)
+  {
+    if (heap._useflag == _FREEENTRY)
+      memset(heap._pentry, value, heap._size);
+  }
+  UNLOCK_HEAP;
+  return retval == _HEAPEND? _HEAPOK : retval;
 }
 
 /*********************************************************************
- *    _heapadd (MSVCRT.@)
+ *             _heapadd (MSVCRT.@)
  */
-int _heapadd(void* mem, size_t size)
+int CDECL _heapadd(void* mem, size_t size)
 {
-  TRACE("(%p,%d) unsupported in Win32\n", mem,size);
+  TRACE("(%p,%ld) unsupported in Win32\n", mem,size);
   *_errno() = ENOSYS;
   return -1;
 }
 
+/*********************************************************************
+ *             _heapadd (MSVCRT.@)
+ */
+intptr_t CDECL _get_heap_handle(void)
+{
+    return (intptr_t)GetProcessHeap();
+}
+
+/*********************************************************************
+ *             _msize (MSVCRT.@)
+ */
+size_t CDECL _msize(void* mem)
+{
+  size_t size = HeapSize(GetProcessHeap(),0,mem);
+  if (size == ~(size_t)0)
+  {
+    WARN(":Probably called with non wine-allocated memory, ret = -1\n");
+    /* At least the Win32 crtdll/msvcrt also return -1 in this case */
+  }
+  return size;
+}
+
+/*********************************************************************
+ *             calloc (MSVCRT.@)
+ */
+void* CDECL calloc(size_t size,size_t count)
+{
+  return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
+}
+
+/*********************************************************************
+ *             free (MSVCRT.@)
+ */
+void CDECL free(void* ptr)
+{
+  HeapFree(GetProcessHeap(),0,ptr);
+}
+
+/*********************************************************************
+ *                  malloc (MSVCRT.@)
+ */
+void* CDECL malloc(size_t size)
+{
+  void *ret = HeapAlloc(GetProcessHeap(),0,size);
+  if (!ret)
+      *_errno() = ENOMEM;
+  return ret;
+}
+
+/*********************************************************************
+ *             realloc (MSVCRT.@)
+ */
+void* CDECL realloc(void* ptr, size_t size)
+{
+  if (!ptr) return malloc(size);
+  if (size) return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
+  free(ptr);
+  return NULL;
+}
+
+/*********************************************************************
+ *             __p__amblksiz (MSVCRT.@)
+ */
+unsigned int* CDECL __p__amblksiz(void)
+{
+  return &MSVCRT_amblksiz;
+}
+
+/*********************************************************************
+ *             _get_sbh_threshold (MSVCRT.@)
+ */
+size_t CDECL _get_sbh_threshold(void)
+{
+  return MSVCRT_sbh_threshold;
+}
+
+/*********************************************************************
+ *             _set_sbh_threshold (MSVCRT.@)
+ */
+int CDECL _set_sbh_threshold(size_t threshold)
+{
+  if(threshold > 1016)
+     return 0;
+  else
+     MSVCRT_sbh_threshold = threshold;
+  return 1;
+}
+
+/*********************************************************************
+ *             _aligned_free (MSVCRT.@)
+ */
 void CDECL _aligned_free(void *memblock)
 {
+    TRACE("(%p)\n", memblock);
+
     if (memblock)
     {
         void **saved = SAVED_PTR(memblock);
@@ -165,9 +350,13 @@ void CDECL _aligned_free(void *memblock)
     }
 }
 
+/*********************************************************************
+ *             _aligned_offset_malloc (MSVCRT.@)
+ */
 void * CDECL _aligned_offset_malloc(size_t size, size_t alignment, size_t offset)
 {
     void *memblock, *temp, **saved;
+    TRACE("(%lu, %lu, %lu)\n", size, alignment, offset);
 
     /* alignment must be a power of 2 */
     if ((alignment & (alignment - 1)) != 0)
@@ -204,16 +393,24 @@ void * CDECL _aligned_offset_malloc(size_t size, size_t alignment, size_t offset
     return memblock;
 }
 
+/*********************************************************************
+ *             _aligned_malloc (MSVCRT.@)
+ */
 void * CDECL _aligned_malloc(size_t size, size_t alignment)
 {
+    TRACE("(%lu, %lu)\n", size, alignment);
     return _aligned_offset_malloc(size, alignment, 0);
 }
 
+/*********************************************************************
+ *             _aligned_offset_realloc (MSVCRT.@)
+ */
 void * CDECL _aligned_offset_realloc(void *memblock, size_t size,
                                      size_t alignment, size_t offset)
 {
     void * temp, **saved;
     size_t old_padding, new_padding, old_size;
+    TRACE("(%p, %lu, %lu, %lu)\n", memblock, size, alignment, offset);
 
     if (!memblock)
         return _aligned_offset_malloc(size, alignment, offset);
@@ -244,7 +441,6 @@ void * CDECL _aligned_offset_realloc(void *memblock, size_t size,
 
     /* make sure alignment and offset didn't change */
     saved = SAVED_PTR(memblock);
-
     if (memblock != ALIGN_PTR(*saved, alignment, offset))
     {
         *_errno() = EINVAL;
@@ -255,7 +451,7 @@ void * CDECL _aligned_offset_realloc(void *memblock, size_t size,
 
     /* Get previous size of block */
     old_size = _msize(*saved);
-    if (old_size == (size_t)-1)
+    if (old_size == -1)
     {
         /* It seems this function was called with an invalid pointer. Bail out. */
         return NULL;
@@ -283,47 +479,116 @@ void * CDECL _aligned_offset_realloc(void *memblock, size_t size,
 
     new_padding = (char *)memblock - (char *)temp;
 
-    /*
-    Memory layout of old block is as follows:
-    +-------+---------------------+-+--------------------------+-----------+
-    |  ...  | "old_padding" bytes | | ... "old_size" bytes ... |    ...    |
-    +-------+---------------------+-+--------------------------+-----------+
-    ^                     ^ ^
-    |                     | |
-    *saved               saved memblock
-
-
-    Memory layout of new block is as follows:
-    +-------+-----------------------------+-+----------------------+-------+
-    |  ...  |    "new_padding" bytes      | | ... "size" bytes ... |  ...  |
-    +-------+-----------------------------+-+----------------------+-------+
-    ^                             ^ ^
-    |                             | |
-    temp                       saved memblock
-
-    However, in the new block, actual data is still written as follows
-    (because it was copied by MSVCRT_realloc):
-    +-------+---------------------+--------------------------------+-------+
-    |  ...  | "old_padding" bytes |   ... "old_size" bytes ...     |  ...  |
-    +-------+---------------------+--------------------------------+-------+
-    ^                             ^ ^
-    |                             | |
-    temp                       saved memblock
-
-    Therefore, min(old_size,size) bytes of actual data have to be moved
-    from the offset they were at in the old block (temp + old_padding),
-    to the offset they have to be in the new block (temp + new_padding == memblock).
-    */
-    
+/*
+   Memory layout of old block is as follows:
+   +-------+---------------------+-+--------------------------+-----------+
+   |  ...  | "old_padding" bytes | | ... "old_size" bytes ... |    ...    |
+   +-------+---------------------+-+--------------------------+-----------+
+           ^                     ^ ^
+           |                     | |
+        *saved               saved memblock
+
+   Memory layout of new block is as follows:
+   +-------+-----------------------------+-+----------------------+-------+
+   |  ...  |    "new_padding" bytes      | | ... "size" bytes ... |  ...  |
+   +-------+-----------------------------+-+----------------------+-------+
+           ^                             ^ ^
+           |                             | |
+          temp                       saved memblock
+
+   However, in the new block, actual data is still written as follows
+   (because it was copied by MSVCRT_realloc):
+   +-------+---------------------+--------------------------------+-------+
+   |  ...  | "old_padding" bytes |   ... "old_size" bytes ...     |  ...  |
+   +-------+---------------------+--------------------------------+-------+
+           ^                             ^ ^
+           |                             | |
+          temp                       saved memblock
+
+   Therefore, min(old_size,size) bytes of actual data have to be moved
+   from the offset they were at in the old block (temp + old_padding),
+   to the offset they have to be in the new block (temp + new_padding == memblock).
+*/
     if (new_padding != old_padding)
         memmove((char *)memblock, (char *)temp + old_padding, (old_size < size) ? old_size : size);
 
     *saved = temp;
 
     return memblock;
- }
+}
 
+/*********************************************************************
+ *             _aligned_realloc (MSVCRT.@)
+ */
 void * CDECL _aligned_realloc(void *memblock, size_t size, size_t alignment)
 {
+    TRACE("(%p, %lu, %lu)\n", memblock, size, alignment);
     return _aligned_offset_realloc(memblock, size, alignment, 0);
 }
+
+/*********************************************************************
+ *             memmove_s (MSVCRT.@)
+ */
+int CDECL memmove_s(void *dest, size_t numberOfElements, const void *src, size_t count)
+{
+    TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count);
+
+    if(!count)
+        return 0;
+
+    if(!dest || !src) {
+        if(dest)
+            memset(dest, 0, numberOfElements);
+
+        *_errno() = EINVAL;
+        return EINVAL;
+    }
+
+    if(count > numberOfElements) {
+        memset(dest, 0, numberOfElements);
+
+        *_errno() = ERANGE;
+        return ERANGE;
+    }
+
+    memmove(dest, src, count);
+    return 0;
+}
+
+/*********************************************************************
+ *             strncpy_s (MSVCRT.@)
+ */
+int CDECL strncpy_s(char *dest, size_t numberOfElements,
+        const char *src, size_t count)
+{
+    size_t i, end;
+
+    TRACE("(%s %lu %s %lu)\n", dest, numberOfElements, src, count);
+
+    if(!count)
+        return 0;
+
+    if(!dest || !src || !numberOfElements) {
+        _invalid_parameter(NULL, NULL, NULL, 0, 0);
+        *_errno() = EINVAL;
+        return EINVAL;
+    }
+
+    if(count!=_TRUNCATE && count<numberOfElements)
+        end = count;
+    else
+        end = numberOfElements-1;
+
+    for(i=0; i<end && src[i]; i++)
+        dest[i] = src[i];
+
+    if(!src[i] || end==count || count==_TRUNCATE) {
+        dest[i] = '\0';
+        return 0;
+    }
+
+    _invalid_parameter(NULL, NULL, NULL, 0, 0);
+    dest[0] = '\0';
+    *_errno() = EINVAL;
+    return EINVAL;
+}