Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

283 lines
7.4 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. wmiguidapi.c
  5. Abstract:
  6. Data structures and functions that generate GUID.
  7. --*/
  8. #include <ntos.h>
  9. #define MAX_CACHED_UUID_TIME 10000 // 10 seconds
  10. #define WMI_UUID_TIME_HIGH_MASK 0x0FFF
  11. #define WMI_UUID_VERSION 0x1000
  12. typedef long WMI_STATUS;
  13. #define WMI_ENTRY __stdcall
  14. #define WMI_S_OUT_OF_MEMORY 14
  15. #define WMI_S_OK 0
  16. #define WMI_S_UUID_LOCAL_ONLY 1824L
  17. //#define RPC_RAND_UUID_VERSION 0x4000
  18. #define WMI_UUID_RESERVED 0x80
  19. #define WMI_UUID_CLOCK_SEQ_HI_MASK 0x3F
  20. extern EtwpSleep(unsigned long dwMilliseconds);
  21. typedef struct _WMI_UUID_GENERATE
  22. {
  23. unsigned long TimeLow;
  24. unsigned short TimeMid;
  25. unsigned short TimeHiAndVersion;
  26. unsigned char ClockSeqHiAndReserved;
  27. unsigned char ClockSeqLow;
  28. unsigned char NodeId[6];
  29. } WMI_UUID_GENERATE;
  30. typedef struct _UUID_CACHED_VALUES_STRUCT
  31. {
  32. ULARGE_INTEGER Time; // Time of last uuid allocation
  33. long AllocatedCount; // Number of UUIDs allocated
  34. unsigned char ClockSeqHiAndReserved;
  35. unsigned char ClockSeqLow;
  36. unsigned char NodeId[6];
  37. } UUID_CACHED_VALUES_STRUCT;
  38. UUID_CACHED_VALUES_STRUCT UuidCachedValues;
  39. WMI_STATUS
  40. EtwpUuidGetValues(
  41. OUT UUID_CACHED_VALUES_STRUCT *Values
  42. )
  43. /*++
  44. Routine Description:
  45. This routine allocates a block of uuids for UuidCreate to handout.
  46. Arguments:
  47. Values - Set to contain everything needed to allocate a block of uuids.
  48. The following fields will be updated here:
  49. NextTimeLow - Together with LastTimeLow, this denotes the boundaries
  50. of a block of Uuids. The values between NextTimeLow
  51. and LastTimeLow are used in a sequence of Uuids returned
  52. by UuidCreate().
  53. LastTimeLow - See NextTimeLow.
  54. ClockSequence - Clock sequence field in the uuid. This is changed
  55. when the clock is set backward.
  56. Return Value:
  57. WMI_S_OK - We successfully allocated a block of uuids.
  58. WMI_S_OUT_OF_MEMORY - As needed.
  59. --*/
  60. {
  61. NTSTATUS NtStatus;
  62. ULARGE_INTEGER Time;
  63. ULONG Range;
  64. ULONG Sequence;
  65. int Tries = 0;
  66. do {
  67. NtStatus = NtAllocateUuids(&Time, &Range, &Sequence, (char *) &Values->NodeId[0]);
  68. if (NtStatus == STATUS_RETRY)
  69. {
  70. EtwpSleep(1);
  71. }
  72. Tries++;
  73. if (Tries == 20)
  74. {
  75. #ifdef DEBUGRPC
  76. PrintToDebugger("Rpc: NtAllocateUuids retried 20 times!\n");
  77. ASSERT(Tries < 20);
  78. #endif
  79. NtStatus = STATUS_UNSUCCESSFUL;
  80. }
  81. } while(NtStatus == STATUS_RETRY);
  82. if (!NT_SUCCESS(NtStatus))
  83. {
  84. return(WMI_S_OUT_OF_MEMORY);
  85. }
  86. // NtAllocateUuids keeps time in SYSTEM_TIME format which is 100ns ticks since
  87. // Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582.
  88. // 17 Days in Oct + 30 (Nov) + 31 (Dec) + 18 years and 5 leap days.
  89. Time.QuadPart += (unsigned __int64) (1000*1000*10) // seconds
  90. * (unsigned __int64) (60 * 60 * 24) // days
  91. * (unsigned __int64) (17+30+31+365*18+5); // # of days
  92. ASSERT(Range);
  93. Values->ClockSeqHiAndReserved =
  94. WMI_UUID_RESERVED | (((unsigned char) (Sequence >> 8))
  95. & (unsigned char) WMI_UUID_CLOCK_SEQ_HI_MASK);
  96. Values->ClockSeqLow = (unsigned char) (Sequence & 0x00FF);
  97. // The order of these assignments is important
  98. Values->Time.QuadPart = Time.QuadPart + (Range - 1);
  99. Values->AllocatedCount = Range;
  100. /*if ((Values->NodeId[0] & 0x80) == 0)
  101. {*/
  102. return(WMI_S_OK);
  103. /*}
  104. return (WMI_S_UUID_LOCAL_ONLY);*/
  105. }
  106. WMI_STATUS WMI_ENTRY
  107. EtwpUuidCreateSequential (
  108. OUT UUID * Uuid
  109. )
  110. /*++
  111. Routine Description:
  112. This routine will create a new UUID (or GUID) which is unique in
  113. time and space. We will try to guarantee that the UUID (or GUID)
  114. we generate is unique in time and space. This means that this
  115. routine may fail if we can not generate one which we can guarantee
  116. is unique in time and space.
  117. Arguments:
  118. Uuid - Returns the generated UUID (or GUID).
  119. Return Value:
  120. WMI_S_OK - The operation completed successfully.
  121. RPC_S_UUID_NO_ADDRESS - We were unable to obtain the ethernet or
  122. token ring address for this machine.
  123. WMI_S_UUID_LOCAL_ONLY - On NT & Chicago if we can't get a
  124. network address. This is a warning to the user, the
  125. UUID is still valid, it just may not be unique on other machines.
  126. WMI_S_OUT_OF_MEMORY - Returned as needed.
  127. --*/
  128. {
  129. WMI_UUID_GENERATE * WmiUuid = (WMI_UUID_GENERATE *) Uuid;
  130. WMI_STATUS Status = WMI_S_OK;
  131. ULARGE_INTEGER Time;
  132. long Delta;
  133. static unsigned long LastTickCount = 0;
  134. if (NtGetTickCount()-LastTickCount > MAX_CACHED_UUID_TIME)
  135. {
  136. UuidCachedValues.AllocatedCount = 0;
  137. LastTickCount = NtGetTickCount();
  138. }
  139. for(;;)
  140. {
  141. Time.QuadPart = UuidCachedValues.Time.QuadPart;
  142. // Copy the static info into the UUID. We can't do this later
  143. // because the clock sequence could be updated by another thread.
  144. *(unsigned long *)&WmiUuid->ClockSeqHiAndReserved =
  145. *(unsigned long *)&UuidCachedValues.ClockSeqHiAndReserved;
  146. *(unsigned long *)&WmiUuid->NodeId[2] =
  147. *(unsigned long *)&UuidCachedValues.NodeId[2];
  148. Delta = InterlockedDecrement(&UuidCachedValues.AllocatedCount);
  149. if (Time.QuadPart != UuidCachedValues.Time.QuadPart)
  150. {
  151. // If our captured time doesn't match the cache then another
  152. // thread already took the lock and updated the cache. We'll
  153. // just loop and try again.
  154. continue;
  155. }
  156. if (Delta >= 0)
  157. {
  158. break;
  159. }
  160. //
  161. // Allocate block of Uuids.
  162. //
  163. Status = EtwpUuidGetValues( &UuidCachedValues );
  164. /* if (Status == WMI_S_OK)
  165. {
  166. UuidCacheValid = CACHE_VALID;
  167. }
  168. else
  169. {
  170. UuidCacheValid = CACHE_LOCAL_ONLY;
  171. }*/
  172. if (Status != WMI_S_OK)
  173. {
  174. #ifdef DEBUGRPC
  175. if (Status != WMI_S_OUT_OF_MEMORY)
  176. PrintToDebugger("RPC: UuidGetValues returned or raised: %x\n", Status);
  177. #endif
  178. ASSERT( (Status == WMI_S_OUT_OF_MEMORY) );
  179. return Status;
  180. }
  181. // Loop
  182. }
  183. Time.QuadPart -= Delta;
  184. WmiUuid->TimeLow = (unsigned long) Time.LowPart;
  185. WmiUuid->TimeMid = (unsigned short) (Time.HighPart & 0x0000FFFF);
  186. WmiUuid->TimeHiAndVersion = (unsigned short)
  187. (( (unsigned short)(Time.HighPart >> 16)
  188. & WMI_UUID_TIME_HIGH_MASK ) | WMI_UUID_VERSION);
  189. // ASSERT( Status == WMI_S_OK
  190. // || Status == WMI_S_UUID_LOCAL_ONLY);
  191. /* if (UuidCacheValid == CACHE_LOCAL_ONLY)
  192. {
  193. return WMI_S_UUID_LOCAL_ONLY;
  194. }*/
  195. return(Status);
  196. }
  197. NTSTATUS
  198. EtwpUuidCreate(
  199. OUT UUID *Uuid
  200. )
  201. {
  202. return (NTSTATUS)EtwpUuidCreateSequential (Uuid );
  203. }