convert.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*++
  2. Copyright (c) 2016 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. convert.c
  9. Abstract:
  10. This module implements the type conversion interface subsystem. The
  11. interfaces are used to translate between C library types and native system
  12. types.
  13. Author:
  14. Chris Stevens 24-Mar-2016
  15. Environment:
  16. User Mode C Library
  17. --*/
  18. //
  19. // ------------------------------------------------------------------- Includes
  20. //
  21. #include "libcp.h"
  22. #include <assert.h>
  23. #include <errno.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. //
  28. // ---------------------------------------------------------------- Definitions
  29. //
  30. //
  31. // ------------------------------------------------------ Data Type Definitions
  32. //
  33. //
  34. // ----------------------------------------------- Internal Function Prototypes
  35. //
  36. //
  37. // -------------------------------------------------------------------- Globals
  38. //
  39. //
  40. // Store the global list of type conversion interfaces, protected by a global
  41. // lock.
  42. //
  43. LIST_ENTRY ClTypeConversionInterfaceList;
  44. pthread_mutex_t ClTypeConversionInterfaceLock;
  45. //
  46. // ------------------------------------------------------------------ Functions
  47. //
  48. BOOL
  49. ClpInitializeTypeConversions (
  50. VOID
  51. )
  52. /*++
  53. Routine Description:
  54. This routine initializes the type conversion subsystem of the C library.
  55. Arguments:
  56. None.
  57. Return Value:
  58. TRUE on success.
  59. FALSE on failure.
  60. --*/
  61. {
  62. INITIALIZE_LIST_HEAD(&ClTypeConversionInterfaceList);
  63. pthread_mutex_init(&ClTypeConversionInterfaceLock, NULL);
  64. return TRUE;
  65. }
  66. LIBC_API
  67. KSTATUS
  68. ClRegisterTypeConversionInterface (
  69. CL_CONVERSION_TYPE Type,
  70. PVOID Interface,
  71. BOOL Register
  72. )
  73. /*++
  74. Routine Description:
  75. This routine registers or deregisters a C library type conversion interface.
  76. Arguments:
  77. Type - Supplies the type of the conversion interface being registered.
  78. Interface - Supplies a pointer to the type conversion interface. This
  79. memory will be used by the library; the caller cannot release it or
  80. stack allocate it.
  81. Register - Supplies a boolean indicating whether or not the given interface
  82. should be registered or de-registered.
  83. Return Value:
  84. Status code.
  85. --*/
  86. {
  87. PLIST_ENTRY CurrentEntry;
  88. PCL_TYPE_CONVERSION_INTERFACE Entry;
  89. PCL_TYPE_CONVERSION_INTERFACE ExistingEntry;
  90. PCL_TYPE_CONVERSION_INTERFACE NewEntry;
  91. KSTATUS Status;
  92. ExistingEntry = NULL;
  93. NewEntry = NULL;
  94. Status = STATUS_SUCCESS;
  95. //
  96. // Allocate and initialize the entry before acquiring the lock.
  97. //
  98. if (Register != FALSE) {
  99. NewEntry = malloc(sizeof(CL_TYPE_CONVERSION_INTERFACE));
  100. if (NewEntry == NULL) {
  101. Status = STATUS_INSUFFICIENT_RESOURCES;
  102. goto RegisterTypeConversionInterfaceEnd;
  103. }
  104. NewEntry->ListEntry.Next = NULL;
  105. NewEntry->Type = Type;
  106. NewEntry->Interface.Buffer = Interface;
  107. }
  108. //
  109. // Look for an existing entry matching the type and interface buffer.
  110. //
  111. pthread_mutex_lock(&ClTypeConversionInterfaceLock);
  112. CurrentEntry = ClTypeConversionInterfaceList.Next;
  113. while (CurrentEntry != &ClTypeConversionInterfaceList) {
  114. Entry = LIST_VALUE(CurrentEntry,
  115. CL_TYPE_CONVERSION_INTERFACE,
  116. ListEntry);
  117. CurrentEntry = CurrentEntry->Next;
  118. if ((Entry->Type == Type) && (Entry->Interface.Buffer == Interface)) {
  119. ExistingEntry = Entry;
  120. break;
  121. }
  122. }
  123. //
  124. // If there was an existing entry, remove and free it if necessary.
  125. //
  126. if (ExistingEntry != NULL) {
  127. if (Register == FALSE) {
  128. LIST_REMOVE(&(ExistingEntry->ListEntry));
  129. ExistingEntry->ListEntry.Next = NULL;
  130. //
  131. // The entry exists and the caller is trying to register it again.
  132. // Clear out the pointer so it's not freed at the end of this routine.
  133. //
  134. } else {
  135. ExistingEntry = NULL;
  136. Status = STATUS_DUPLICATE_ENTRY;
  137. }
  138. //
  139. // There was no previous entry, add the new one if needed.
  140. //
  141. } else {
  142. if (Register != FALSE) {
  143. INSERT_AFTER(&(NewEntry->ListEntry),
  144. &ClTypeConversionInterfaceList);
  145. NewEntry = NULL;
  146. }
  147. }
  148. RegisterTypeConversionInterfaceEnd:
  149. pthread_mutex_unlock(&ClTypeConversionInterfaceLock);
  150. if (ExistingEntry != NULL) {
  151. ASSERT(ExistingEntry->ListEntry.Next == NULL);
  152. free(ExistingEntry);
  153. }
  154. if (NewEntry != NULL) {
  155. ASSERT(NewEntry->ListEntry.Next == NULL);
  156. free(NewEntry);
  157. }
  158. return Status;
  159. }
  160. //
  161. // --------------------------------------------------------- Internal Functions
  162. //