Logo Search packages:      
Sourcecode: ndiswrapper version File versions  Download package

rtl.c

/*
 *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 */

#include "ntoskernel.h"

int rtl_init(void)
{
      return 0;
}

/* called when module is being removed */
void rtl_exit(void)
{
      TRACEEXIT4(return);
}

wstdcall SIZE_T WIN_FUNC(RtlCompareMemory,3)
      (const void *a, const void *b, SIZE_T len)
{
      size_t i;
      char *x, *y;

      TRACEENTER1("");

      x = (char *)a;
      y = (char *)b;
      /* MSDN says this should return number of bytes that compare as
       * equal. This can be interpretted as either all bytes that are
       * equal in 'len' bytes or that only until the bytes compare as
       * not equal. Initially we had it the former way, but Realtek driver
       * doesn't like it that way - it takes many attempts to associate
       * with WPA. ReactOS returns the number of bytes that are equal
       * upto when they compare as not equal.
       * According to lords at #reactos, that is the way it should be
       * and that msdn is wrong about it!
       */
      for (i = 0; i < len && x[i] == y[i]; i++)
            ;
      return i;
}

wstdcall void WIN_FUNC(RtlCopyMemory,3)
      (void *dst, const void *src, SIZE_T length)
{
      memcpy(dst, src, length);
}

wstdcall void WIN_FUNC(RtlZeroMemory,2)
      (void *dst, SIZE_T length)
{
      memset(dst, 0, length);
}

wstdcall void WIN_FUNC(RtlSecureZeroMemory,2)
      (void *dst, SIZE_T length)
{
      memset(dst, 0, length);
}

wstdcall void WIN_FUNC(RtlFillMemory,3)
      (void *dest, SIZE_T length, UCHAR fill)
{
      memset(dest, fill, length);
}

wstdcall void WIN_FUNC(RtlMoveMemory,3)
      (void *dest, const void *src, SIZE_T length)
{
      memmove(dest, src, length);
}

wstdcall LONG WIN_FUNC(RtlCompareString,3)
      (const struct ansi_string *s1, const struct ansi_string *s2,
       BOOLEAN case_insensitive)
{
      unsigned int len;
      LONG ret = 0;
      const char *p1, *p2;

      TRACEENTER2("");
      len = min(s1->length, s2->length);
      p1 = s1->buf;
      p2 = s2->buf;
      if (case_insensitive)
            while (!ret && len--)
                  ret = toupper(*p1++) - toupper(*p2++);
      else
            while (!ret && len--)
                  ret = *p1++ - *p2++;
      if (!ret)
            ret = s1->length - s2->length;
      TRACEEXIT2(return ret);
}

wstdcall LONG WIN_FUNC(RtlCompareUnicodeString,3)
      (const struct unicode_string *s1, const struct unicode_string *s2,
       BOOLEAN case_insensitive)
{
      unsigned int len;
      LONG ret = 0;
      const wchar_t *p1, *p2;

      TRACEENTER2("");

      len = min(s1->length, s2->length) / sizeof(wchar_t);
      p1 = s1->buf;
      p2 = s2->buf;
      if (case_insensitive)
            while (!ret && len--)
                  ret = toupper((u8)*p1++) - toupper((u8)*p2++);
      else
            while (!ret && len--)
                  ret = (u8)*p1++ - (u8)*p2++;
      if (!ret)
            ret = s1->length - s2->length;
      DBGTRACE2("len: %d, ret: %d", len, ret);
      TRACEEXIT2(return ret);
}

wstdcall BOOLEAN WIN_FUNC(RtlEqualString,3)
      (const struct ansi_string *s1, const struct ansi_string *s2,
       BOOLEAN case_insensitive)
{
      TRACEENTER1("");
      if (s1->length != s2->length)
            return FALSE;
      return !RtlCompareString(s1, s2, case_insensitive);
}

wstdcall BOOLEAN WIN_FUNC(RtlEqualUnicodeString,3)
      (const struct unicode_string *s1, const struct unicode_string *s2,
       BOOLEAN case_insensitive)
{
      if (s1->length != s2->length)
            return FALSE;
      return !RtlCompareUnicodeString(s1, s2, case_insensitive);
}

wstdcall void WIN_FUNC(RtlCopyUnicodeString,2)
      (struct unicode_string *dst, struct unicode_string *src)
{
      TRACEENTER1("%p, %p", dst, src);
      if (src && src->buf && dst->buf) {
            dst->length = min(src->length, dst->max_length);
            memcpy(dst->buf, src->buf, dst->length);
            if (dst->length < dst->max_length)
                  dst->buf[dst->length / sizeof(dst->buf[0])] = 0;
      } else
            dst->length = 0;
      TRACEEXIT1(return);
}

wstdcall void WIN_FUNC(RtlCopyString,2)
      (struct ansi_string *dst, struct ansi_string *src)
{
      TRACEENTER1("%p, %p", dst, src);
      if (src && src->buf && dst->buf) {
            dst->length = min(src->length, dst->max_length);
            memcpy(dst->buf, src->buf, dst->length);
            if (dst->length < dst->max_length)
                  dst->buf[dst->length] = 0;
      } else
            dst->length = 0;
      TRACEEXIT1(return);
}

wstdcall NTSTATUS WIN_FUNC(RtlAppendUnicodeToString,2)
      (struct unicode_string *dst, wchar_t *src)
{
      if (src) {
            int len;
            for (len = 0; src[len]; len++)
                  ;
            if (dst->length + (len * sizeof(dst->buf[0])) > dst->max_length)
                  return STATUS_BUFFER_TOO_SMALL;
            memcpy(&dst->buf[dst->length], src, len * sizeof(dst->buf[0]));
            dst->length += len * sizeof(dst->buf[0]);
            if (dst->max_length > dst->length)
                  dst->buf[dst->length / sizeof(dst->buf[0])] = 0;
      }
      return STATUS_SUCCESS;
}

wstdcall NTSTATUS WIN_FUNC(RtlAppendUnicodeStringToString,2)
      (struct unicode_string *dst, struct unicode_string *src)
{
      if (dst->max_length < src->length + dst->length)
            return STATUS_BUFFER_TOO_SMALL;
      if (src->length) {
            memcpy(&dst->buf[dst->length], src->buf, src->length);
            dst->length += src->length;
            if (dst->max_length > dst->length)
                  dst->buf[dst->length / sizeof(dst->buf[0])] = 0;
      }
      TRACEEXIT2(return STATUS_SUCCESS);
}

wstdcall ULONG WIN_FUNC(RtlxAnsiStringToUnicodeSize,1)
      (const struct ansi_string *string)
{
      int i;

      for (i = 0; i < string->max_length && string->buf[i]; i++)
            ;
      return (i * sizeof(wchar_t));
}

wstdcall ULONG WIN_FUNC(RtlxUnicodeStringToAnsiSize,1)
      (const struct unicode_string *string)
{
      int i;

      for (i = 0; i < string->max_length && string->buf[i]; i++)
            ;
      return i;
}

wstdcall NTSTATUS WIN_FUNC(RtlAnsiStringToUnicodeString,3)
      (struct unicode_string *dst, const struct ansi_string *src,
       BOOLEAN alloc)
{
      int i, n;

      n = RtlxAnsiStringToUnicodeSize(src);
      DBGTRACE2("%d, %d, %d, %d, %p", n, dst->max_length, src->length,
              src->max_length, src->buf);
      if (alloc == TRUE) {
#if 0
            if (n == 0) {
                  dst->length = dst->max_length = 0;
                  dst->buf = NULL;
                  TRACEEXIT2(return STATUS_SUCCESS);
            }
#endif
            dst->max_length = n + sizeof(dst->buf[0]);
            dst->buf = ExAllocatePoolWithTag(NonPagedPool,
                                     dst->max_length, 0);
            if (!dst->buf) {
                  dst->max_length = dst->length = 0;
                  TRACEEXIT2(return STATUS_NO_MEMORY);
            }
      } else if (dst->max_length < n)
            TRACEEXIT2(return STATUS_BUFFER_TOO_SMALL);

      dst->length = n;
      n /= sizeof(dst->buf[0]);
      for (i = 0; i < n; i++)
            dst->buf[i] = src->buf[i];
      if (i * sizeof(dst->buf[0]) < dst->max_length)
            dst->buf[i] = 0;
      DBGTRACE2("dst: length: %d, max_length: %d, string: %p",
              dst->length, dst->max_length, src->buf);
      TRACEEXIT2(return STATUS_SUCCESS);
}

wstdcall NTSTATUS WIN_FUNC(RtlUnicodeStringToAnsiString,3)
      (struct ansi_string *dst, const struct unicode_string *src,
       BOOLEAN alloc)
{
      int i, n;

      n = RtlxUnicodeStringToAnsiSize(src);
      DBGTRACE2("%d, %d, %d, %d, %p", n, dst->max_length, src->length,
              src->max_length, src->buf);
      if (alloc == TRUE) {
#if 0
            if (n == 0) {
                  dst->length = dst->max_length = 0;
                  dst->buf = NULL;
                  TRACEEXIT2(return STATUS_SUCCESS);
            }
#endif
            dst->max_length = n + sizeof(dst->buf[0]);
            dst->buf = ExAllocatePoolWithTag(NonPagedPool,
                                     dst->max_length, 0);
            if (!dst->buf) {
                  dst->max_length = dst->length = 0;
                  TRACEEXIT1(return STATUS_NO_MEMORY);
            }
      } else if (dst->max_length < n)
            TRACEEXIT2(return STATUS_BUFFER_TOO_SMALL);

      dst->length = n;
      for (i = 0; i < n; i++)
            dst->buf[i] = src->buf[i];
      if (i < dst->max_length)
            dst->buf[i] = 0;
      DBGTRACE2("string: %p, len: %d(%d)", dst->buf, dst->length,
              dst->max_length);
      TRACEEXIT2(return STATUS_SUCCESS);
}

wstdcall NTSTATUS WIN_FUNC(RtlUnicodeStringToInteger,3)
      (struct unicode_string *ustring, ULONG base, ULONG *value)
{
      int i, negsign;
      wchar_t *str;

      *value = 0;
      if (ustring->length == 0)
            return STATUS_SUCCESS;

      str = ustring->buf;
      negsign = 0;
      i = 0;
      switch ((char)str[i]) {
      case '-':
            negsign = 1;
            /* fall through */
      case '+':
            i++;
            break;
      }

      if (base == 0 && i < ustring->length && str[i]) {
            switch(tolower((char)str[i])) {
            case 'x':
                  base = 16;
                  i++;
                  break;
            case 'o':
                  base = 8;
                  i++;
                  break;
            case 'b':
                  base = 2;
                  i++;
                  break;
            default:
                  base = 10;
                  break;
            }
      }
      if (!(base == 2 || base == 8 || base == 10 || base == 16))
            return STATUS_INVALID_PARAMETER;

      for ( ; i < ustring->length && str[i]; i++) {
            int r;
            char c = tolower((char)str[i]);

            if (c >= '0' && c <= '9')
                  r = c - '0';
            else if (c >= 'a' && c <= 'f')
                  r = c - 'a' + 10;
            else
                  break;
            if (r >= base)
                  break;
            *value = *value * base + r;
      }
      if (negsign)
            *value *= -1;

      return STATUS_SUCCESS;
}

wstdcall NTSTATUS WIN_FUNC(RtlIntegerToUnicodeString,3)
      (ULONG value, ULONG base, struct unicode_string *ustring)
{
      typeof(ustring->buf) buf = ustring->buf;
      int i;

      if (base == 0)
            base = 10;
      if (!(base == 2 || base == 8 || base == 10 || base == 16))
            return STATUS_INVALID_PARAMETER;
      for (i = 0; value && i * sizeof(buf[0]) < ustring->max_length; i++) {
            int r;
            r = value % base;
            value /= base;
            if (r < 10)
                  buf[i] = r + '0';
            else
                  buf[i] = r + 'a' - 10;
      }
      if (value)
            return STATUS_BUFFER_OVERFLOW;
      ustring->length = i * sizeof(buf[0]);
      return STATUS_SUCCESS;
}

wstdcall LARGE_INTEGER WIN_FUNC(RtlConvertUlongToLargeInteger,1)
      (ULONG ul)
{
      LARGE_INTEGER li = ul;
      return li;
}

wfastcall USHORT WIN_FUNC(RtlUShortByteSwap,1)
      (USHORT src)
{
      return __swab16(src);
}

wfastcall ULONG WIN_FUNC(RtlUlongByteSwap,1)
      (ULONG src)
{
      /* ULONG is 32 bits for both 32-bit and 64-bit architectures */
      return __swab32(src);
}

wstdcall NTSTATUS WIN_FUNC(NdisUpcaseUnicodeString,2)
      (struct unicode_string *dst, struct unicode_string *src)
{
      USHORT i, n;

      n = min(src->length, src->max_length);
      n = min(n, dst->length);
      n = min(n, dst->max_length);
      n /= sizeof(dst->buf[0]);
      for (i = 0; i < n; i++) {
            char *c = (char *)&dst->buf[i];
            *c = toupper(src->buf[i]);
      }
      TRACEEXIT3(return STATUS_SUCCESS);
}

wstdcall void WIN_FUNC(RtlInitUnicodeString,2)
      (struct unicode_string *dst, const wchar_t *src)
{
      TRACEENTER2("%p", dst);
      if (dst == NULL)
            TRACEEXIT1(return);
      if (src == NULL) {
            dst->max_length = dst->length = 0;
            dst->buf = NULL;
      } else {
            int i;
            for (i = 0; (char)src[i]; i++)
                  ;
            dst->buf = (typeof(dst->buf))src;
            dst->length = i * sizeof(dst->buf[0]);
            dst->max_length = (i + 1) * sizeof(dst->buf[0]);
      }
      TRACEEXIT1(return);
}

wstdcall void WIN_FUNC(RtlInitAnsiString,2)
      (struct ansi_string *dst, const char *src)
{
      TRACEENTER2("%p", dst);
      if (dst == NULL)
            TRACEEXIT2(return);
      if (src == NULL) {
            dst->max_length = dst->length = 0;
            dst->buf = NULL;
      } else {
            int i;
            for (i = 0; src[i]; i++)
                  ;
            dst->buf = (typeof(dst->buf))src;
            dst->length = i;
            dst->max_length = i + 1;
      }
      DBGTRACE2("%p", dst->buf);
      TRACEEXIT2(return);
}

wstdcall void WIN_FUNC(RtlInitString,2)
      (struct ansi_string *dst, const char *src)
{
      TRACEENTER2("%p", dst);
      RtlInitAnsiString(dst, src);
      TRACEEXIT2(return);
}

wstdcall void WIN_FUNC(RtlFreeUnicodeString,1)
      (struct unicode_string *string)
{
      TRACEENTER2("%p", string);
      if (string == NULL)
            return;
      if (string->buf)
            ExFreePool(string->buf);
      string->length = string->max_length = 0;
      string->buf = NULL;
      return;
}

wstdcall void WIN_FUNC(RtlFreeAnsiString,1)
      (struct ansi_string *string)
{
      TRACEENTER2("%p", string);
      if (string == NULL)
            return;
      if (string->buf)
            ExFreePool(string->buf);
      string->length = string->max_length = 0;
      string->buf = NULL;
      return;
}

/* guid string is of the form: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
wstdcall NTSTATUS WIN_FUNC(RtlGUIDFromString,2)
      (struct unicode_string *guid_string, struct guid *guid)
{
      struct ansi_string ansi;
      NTSTATUS ret;
      int i, j, k, l, m;

      ret = RtlUnicodeStringToAnsiString(&ansi, guid_string, TRUE);
      if (ret != STATUS_SUCCESS)
            return ret;
      if (ansi.length != 37 || ansi.buf[0] != '{' ||
          ansi.buf[36] != '}' || ansi.buf[9] != '-' ||
          ansi.buf[14] != '-' || ansi.buf[19] != '-' ||
          ansi.buf[24] != '-') {
            RtlFreeAnsiString(&ansi);
            TRACEEXIT2(return STATUS_INVALID_PARAMETER);
      }
      memcpy(&guid->data4, &ansi.buf[29], sizeof(guid->data3));
      /* set end of data3 for scanf */
      ansi.buf[29] = 0;
      if (sscanf(&ansi.buf[1], "%x", &i) == 1 &&
          sscanf(&ansi.buf[10], "%x", &j) == 1 &&
          sscanf(&ansi.buf[15], "%x", &k) == 1 &&
          sscanf(&ansi.buf[20], "%x", &l) == 1 &&
          sscanf(&ansi.buf[25], "%x", &m) == 1) {
            guid->data1 = (i << 16) | (j < 8) | k;
            guid->data2 = l;
            guid->data3 = m;
            ret = STATUS_SUCCESS;
      } else
            ret = STATUS_INVALID_PARAMETER;
      RtlFreeAnsiString(&ansi);
      return ret;
}

wstdcall NTSTATUS WIN_FUNC(RtlQueryRegistryValues,5)
      (ULONG relative, wchar_t *path, struct rtl_query_registry_table *tbl,
       void *context, void *env)
{
      struct ansi_string ansi;
      struct unicode_string unicode;
      NTSTATUS status, ret;
      static int i = 0;

      TRACEENTER3("%x, %p", relative, tbl);
//    TODO();

      RtlInitUnicodeString(&unicode, path);
      if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
          STATUS_SUCCESS) {
            DBGTRACE2("%s", ansi.buf);
            RtlFreeAnsiString(&ansi);
      }
      ret = STATUS_SUCCESS;
      for (; tbl->name; tbl++) {
            RtlInitUnicodeString(&unicode, tbl->name);
            if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
                STATUS_SUCCESS) {
                  DBGTRACE2("name: %s", ansi.buf);
                  RtlFreeAnsiString(&ansi);
            }
            DBGTRACE2("flags: %08X", tbl->flags);
            if (tbl->flags == RTL_QUERY_REGISTRY_DIRECT) {
                  DBGTRACE2("type: %08X", tbl->def_type);
                  if (tbl->def_type == REG_DWORD) {
                        /* Atheros USB driver needs this, but
                         * don't know where and how to get its
                         * value */
                        if (tbl->def_data) {
                              DBGTRACE2("def_data: %x",
                                      *(int *)tbl->def_data);
                              *(DWORD *)tbl->context = 0x5f292a + i++;
//                                  *(DWORD *)tbl->def_data;
                        } else
                              *(DWORD *)tbl->context = 0x2345dbe;
                  }
            } else {
                  void *data;
                  ULONG type, length;

                  if (!tbl->query_func) {
                        ERROR("oops: no query_func");
                        ret = STATUS_INVALID_PARAMETER;
                        break;
                  }
                  if (tbl->flags & RTL_QUERY_REGISTRY_NOVALUE) {
                        data = NULL;
                        type = REG_NONE;
                        length = 0;
                  } else {
                        data = tbl->def_data;
                        type = tbl->def_type;
                        length = tbl->def_length;;
                  }
                  DBGTRACE2("calling query_func: %p", tbl->query_func);
                  status = LIN2WIN6(tbl->query_func, tbl->name, type,
                                data, length, context, env);
                  DBGTRACE2("status: %08X", status);
                  if (status) {
                        if (status == STATUS_BUFFER_TOO_SMALL)
                              ret = STATUS_BUFFER_TOO_SMALL;
                        else
                              TRACEEXIT2(return STATUS_INVALID_PARAMETER);
                  }
            }
      }
      TRACEEXIT3(return ret);
}

wstdcall NTSTATUS WIN_FUNC(RtlWriteRegistryValue,6)
      (ULONG relative, wchar_t *path, wchar_t *name, ULONG type,
       void *data, ULONG length)
{
      struct ansi_string ansi;
      struct unicode_string unicode;

      TRACEENTER3("%d", relative);
      TODO();

      RtlInitUnicodeString(&unicode, path);
      if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
          STATUS_SUCCESS) {
            DBGTRACE2("%s", ansi.buf);
            RtlFreeAnsiString(&ansi);
      }
      RtlInitUnicodeString(&unicode, name);
      if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) ==
          STATUS_SUCCESS) {
            DBGTRACE2("%s", ansi.buf);
            RtlFreeAnsiString(&ansi);
      }
      TRACEEXIT5(return STATUS_SUCCESS);
}

wstdcall NTSTATUS WIN_FUNC(RtlDeleteRegistryValue,3)
      (ULONG relative, wchar_t *path, wchar_t *name)
{
      return STATUS_SUCCESS;
}

wstdcall void WIN_FUNC(RtlAssert,4)
      (char *failed_assertion, char *file_name, ULONG line_num, char *message)
{
      ERROR("assertion '%s' failed at %s line %d%s",
            failed_assertion, file_name, line_num, message ? message : "");
      return;
}

void WIN_FUNC(RtlUnwind,0)
      (void)
{
      TODO();
}

#include "rtl_exports.h"

Generated by  Doxygen 1.6.0   Back to index