intrface.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. intrface.c
  5. Abstract:
  6. This module implements support for device interfaces.
  7. Author:
  8. Evan Green 19-Sep-2012
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/kernel.h>
  16. #include "iop.h"
  17. //
  18. // ---------------------------------------------------------------- Definitions
  19. //
  20. //
  21. // ------------------------------------------------------ Data Type Definitions
  22. //
  23. /*++
  24. Structure Description:
  25. This structure defines an interface directory, which contains device
  26. interface instances and listeners.
  27. Members:
  28. Header - Supplies the standard object manager header.
  29. Uuid - Supplies the UUID of the interface.
  30. --*/
  31. typedef struct _INTERFACE_DIRECTORY {
  32. OBJECT_HEADER Header;
  33. UUID Uuid;
  34. } INTERFACE_DIRECTORY, *PINTERFACE_DIRECTORY;
  35. /*++
  36. Structure Description:
  37. This structure defines a device interface instance.
  38. Members:
  39. Header - Stores the object manager header.
  40. Device - Stores a pointer to the device this interface is attached to.
  41. InterfaceBuffer - Stores a pointer to the interface buffer.
  42. InterfaceBufferSize - Stores the size of the interface buffer.
  43. --*/
  44. typedef struct _DEVICE_INTERFACE_INSTANCE {
  45. OBJECT_HEADER Header;
  46. PDEVICE Device;
  47. PVOID InterfaceBuffer;
  48. ULONG InterfaceBufferSize;
  49. } DEVICE_INTERFACE_INSTANCE, *PDEVICE_INTERFACE_INSTANCE;
  50. /*++
  51. Structure Description:
  52. This structure defines an interface listener.
  53. Members:
  54. Header - Stores the standard object manager header.
  55. CallbackRoutine - Stores a pointer to the listener's callback routine.
  56. Device - Stores an optional pointer to a specific device to listen to.
  57. Context - Stores a pointer supplied by and passed back to the interface
  58. listener during notifications.
  59. --*/
  60. typedef struct _INTERFACE_LISTENER {
  61. OBJECT_HEADER Header;
  62. PINTERFACE_NOTIFICATION_CALLBACK CallbackRoutine;
  63. PDEVICE Device;
  64. PVOID Context;
  65. } INTERFACE_LISTENER, *PINTERFACE_LISTENER;
  66. //
  67. // ----------------------------------------------- Internal Function Prototypes
  68. //
  69. VOID
  70. IopNotifyInterfaceListeners (
  71. PINTERFACE_DIRECTORY InterfaceDirectory,
  72. PDEVICE_INTERFACE_INSTANCE InterfaceInstance,
  73. PDEVICE Device,
  74. BOOL Arrival
  75. );
  76. VOID
  77. IopPrintUuidToString (
  78. PSTR String,
  79. ULONG StringSize,
  80. PUUID Uuid
  81. );
  82. //
  83. // -------------------------------------------------------------------- Globals
  84. //
  85. //
  86. // Store a pointer to the directory of all exposed interfaces.
  87. //
  88. POBJECT_HEADER IoInterfaceDirectory = NULL;
  89. PQUEUED_LOCK IoInterfaceLock = NULL;
  90. //
  91. // ------------------------------------------------------------------ Functions
  92. //
  93. KERNEL_API
  94. KSTATUS
  95. IoCreateInterface (
  96. PUUID InterfaceUuid,
  97. PDEVICE Device,
  98. PVOID InterfaceBuffer,
  99. ULONG InterfaceBufferSize
  100. )
  101. /*++
  102. Routine Description:
  103. This routine creates a device interface. Interfaces start out disabled. The
  104. Interface/device pair must be unique, there cannot be two interfaces for
  105. the same UUID and device.
  106. Arguments:
  107. InterfaceUuid - Supplies a pointer to the UUID identifying the interface.
  108. Device - Supplies a pointer to the device exposing the interface.
  109. InterfaceBuffer - Supplies a pointer to the interface buffer.
  110. InterfaceBufferSize - Supplies the size of the interface buffer, in bytes.
  111. Return Value:
  112. STATUS_SUCCESS on success.
  113. STATUS_INVALID_PARAMETER if the interface or device were not specified.
  114. STATUS_NO_MEMORY if allocations could not be made.
  115. STATUS_DUPLICATE_ENTRY if an interface already exists for this device.
  116. --*/
  117. {
  118. PINTERFACE_DIRECTORY InterfaceDirectory;
  119. PDEVICE_INTERFACE_INSTANCE InterfaceInstance;
  120. CHAR Name[UUID_STRING_LENGTH + 1];
  121. ULONG NameLength;
  122. KSTATUS Status;
  123. if ((InterfaceUuid == NULL) || (Device == NULL)) {
  124. return STATUS_INVALID_PARAMETER;
  125. }
  126. IopPrintUuidToString(Name, UUID_STRING_LENGTH + 1, InterfaceUuid);
  127. KeAcquireQueuedLock(IoInterfaceLock);
  128. //
  129. // Look up the interface directory. Create it if it does not exist.
  130. //
  131. InterfaceDirectory = ObFindObject(Name,
  132. UUID_STRING_LENGTH + 1,
  133. IoInterfaceDirectory);
  134. if (InterfaceDirectory == NULL) {
  135. InterfaceDirectory = ObCreateObject(ObjectInterface,
  136. IoInterfaceDirectory,
  137. Name,
  138. sizeof(Name),
  139. sizeof(INTERFACE_DIRECTORY),
  140. NULL,
  141. 0,
  142. DEVICE_INTERFACE_ALLOCATION_TAG);
  143. if (InterfaceDirectory == NULL) {
  144. Status = STATUS_NO_MEMORY;
  145. goto CreateInterfaceEnd;
  146. }
  147. InterfaceDirectory->Uuid = *InterfaceUuid;
  148. }
  149. ASSERT(UUID_STRING_LENGTH + 1 > ((sizeof(UINTN) * 2) + 1));
  150. //
  151. // Attempt to open the interface instance for this device. If this succeeds,
  152. // fail this function.
  153. //
  154. NameLength = RtlPrintToString(Name,
  155. UUID_STRING_LENGTH + 1,
  156. CharacterEncodingDefault,
  157. "%08x",
  158. Device);
  159. if (NameLength > UUID_STRING_LENGTH + 1) {
  160. NameLength = UUID_STRING_LENGTH + 1;
  161. }
  162. InterfaceInstance = ObFindObject(Name,
  163. NameLength,
  164. (POBJECT_HEADER)InterfaceDirectory);
  165. if (InterfaceInstance != NULL) {
  166. ObReleaseReference(InterfaceInstance);
  167. Status = STATUS_DUPLICATE_ENTRY;
  168. goto CreateInterfaceEnd;
  169. }
  170. InterfaceInstance = ObCreateObject(ObjectInterfaceInstance,
  171. InterfaceDirectory,
  172. Name,
  173. sizeof(Name),
  174. sizeof(DEVICE_INTERFACE_INSTANCE),
  175. NULL,
  176. 0,
  177. DEVICE_INTERFACE_ALLOCATION_TAG);
  178. if (InterfaceInstance == NULL) {
  179. Status = STATUS_NO_MEMORY;
  180. }
  181. InterfaceInstance->Device = Device;
  182. InterfaceInstance->InterfaceBuffer = InterfaceBuffer;
  183. InterfaceInstance->InterfaceBufferSize = InterfaceBufferSize;
  184. //
  185. // Notify listeners of the interface arrival.
  186. //
  187. IopNotifyInterfaceListeners(InterfaceDirectory,
  188. InterfaceInstance,
  189. Device,
  190. TRUE);
  191. Status = STATUS_SUCCESS;
  192. CreateInterfaceEnd:
  193. KeReleaseQueuedLock(IoInterfaceLock);
  194. if (InterfaceDirectory != NULL) {
  195. ObReleaseReference(InterfaceDirectory);
  196. }
  197. return Status;
  198. }
  199. KERNEL_API
  200. KSTATUS
  201. IoDestroyInterface (
  202. PUUID InterfaceUuid,
  203. PDEVICE Device,
  204. PVOID InterfaceBuffer
  205. )
  206. /*++
  207. Routine Description:
  208. This routine destroys a previously created interface. All parties
  209. registered for notifications on this interface will be notified that the
  210. interface is going down.
  211. Arguments:
  212. InterfaceUuid - Supplies a pointer to the UUID identifying the interface.
  213. Device - Supplies a pointer to the device supplied on registration.
  214. InterfaceBuffer - Supplies a pointer to the interface buffer for the
  215. specific interface to tear down. This needs to match the interface
  216. buffer used when the interface was created.
  217. Return Value:
  218. STATUS_SUCCESS on success.
  219. STATUS_INVALID_PARAMETER if the interface or device is invalid.
  220. STATUS_NOT_FOUND if the interface could not be found.
  221. --*/
  222. {
  223. PINTERFACE_DIRECTORY InterfaceDirectory;
  224. PDEVICE_INTERFACE_INSTANCE InterfaceInstance;
  225. CHAR Name[UUID_STRING_LENGTH + 1];
  226. ULONG NameLength;
  227. KSTATUS Status;
  228. if (InterfaceUuid == NULL) {
  229. return STATUS_INVALID_PARAMETER;
  230. }
  231. IopPrintUuidToString(Name, UUID_STRING_LENGTH + 1, InterfaceUuid);
  232. KeAcquireQueuedLock(IoInterfaceLock);
  233. //
  234. // Look up the interface directory.
  235. //
  236. InterfaceDirectory = ObFindObject(Name,
  237. UUID_STRING_LENGTH + 1,
  238. IoInterfaceDirectory);
  239. if (InterfaceDirectory == NULL) {
  240. Status = STATUS_NOT_FOUND;
  241. goto DeleteInterfaceEnd;
  242. }
  243. //
  244. // Look up the interface instance.
  245. //
  246. NameLength = RtlPrintToString(Name,
  247. UUID_STRING_LENGTH + 1,
  248. CharacterEncodingDefault,
  249. "%08x",
  250. Device);
  251. if (NameLength > UUID_STRING_LENGTH + 1) {
  252. NameLength = UUID_STRING_LENGTH + 1;
  253. }
  254. InterfaceInstance = ObFindObject(Name,
  255. NameLength,
  256. (POBJECT_HEADER)InterfaceDirectory);
  257. if (InterfaceInstance == NULL) {
  258. Status = STATUS_NOT_FOUND;
  259. goto DeleteInterfaceEnd;
  260. }
  261. //
  262. // TODO: Rework the data structures for interfaces. There's no need to
  263. // use the object manager.
  264. //
  265. ASSERT(InterfaceInstance->InterfaceBuffer == InterfaceBuffer);
  266. //
  267. // Notify listeners that the interface is going down.
  268. //
  269. IopNotifyInterfaceListeners(InterfaceDirectory,
  270. InterfaceInstance,
  271. Device,
  272. FALSE);
  273. //
  274. // Remove the reference from the interface, once because of the find and
  275. // another because of the initial creation.
  276. //
  277. ObReleaseReference(InterfaceInstance);
  278. ObReleaseReference(InterfaceInstance);
  279. Status = STATUS_SUCCESS;
  280. DeleteInterfaceEnd:
  281. //
  282. // If necessary, release the pointer to the interface directory added by
  283. // finding it.
  284. //
  285. if (InterfaceDirectory != NULL) {
  286. ObReleaseReference(InterfaceDirectory);
  287. }
  288. KeReleaseQueuedLock(IoInterfaceLock);
  289. return Status;
  290. }
  291. KERNEL_API
  292. KSTATUS
  293. IoRegisterForInterfaceNotifications (
  294. PUUID Interface,
  295. PINTERFACE_NOTIFICATION_CALLBACK CallbackRoutine,
  296. PDEVICE Device,
  297. PVOID Context,
  298. BOOL NotifyForExisting
  299. )
  300. /*++
  301. Routine Description:
  302. This routine registers the given handler to be notified when the given
  303. interface arrives or disappears. Callers are notified of both events.
  304. Callers will be notified for all interface arrivals and removals of the
  305. given interface.
  306. Arguments:
  307. Interface - Supplies a pointer to the UUID identifying the interface.
  308. CallbackRoutine - Supplies a pointer to the callback routine to notify
  309. when an interface arrives or is removed.
  310. Device - Supplies an optional pointer to a device. If this device is
  311. non-NULL, then interface notifications will be restricted to the given
  312. device.
  313. Context - Supplies an optional pointer to a context that will be passed
  314. back to the caller during notifications.
  315. NotifyForExisting - Supplies TRUE if the caller would like an arrival
  316. notification for every pre-existing interface, or FALSE if the caller
  317. only wants to be notified about future arrivals. The caller will be
  318. notified about ALL removals no matter the state of this flag.
  319. Return Value:
  320. STATUS_SUCCESS on success.
  321. STATUS_INVALID_PARAMETER if an invalid interface or callback routine was
  322. supplied.
  323. STATUS_NO_MEMORY if memory could not be allocated to satisfy the request.
  324. STATUS_INSUFFICIENT_RESOURCES if general resources could not be allocated to
  325. satisfy the request.
  326. STATUS_DUPLICATE_ENTRY if the given routine is already registered for
  327. notification on the device.
  328. --*/
  329. {
  330. PLIST_ENTRY CurrentEntry;
  331. PDEVICE_INTERFACE_INSTANCE CurrentInterface;
  332. PINTERFACE_DIRECTORY InterfaceDirectory;
  333. PINTERFACE_LISTENER InterfaceListener;
  334. CHAR Name[UUID_STRING_LENGTH + 1];
  335. KSTATUS Status;
  336. if ((Interface == NULL) || (CallbackRoutine == NULL)) {
  337. return STATUS_INVALID_PARAMETER;
  338. }
  339. IopPrintUuidToString(Name, UUID_STRING_LENGTH + 1, Interface);
  340. KeAcquireQueuedLock(IoInterfaceLock);
  341. //
  342. // Look up the interface directory. Create it if it doesn't exist.
  343. //
  344. InterfaceDirectory = ObFindObject(Name,
  345. UUID_STRING_LENGTH + 1,
  346. IoInterfaceDirectory);
  347. if (InterfaceDirectory == NULL) {
  348. InterfaceDirectory = ObCreateObject(ObjectInterface,
  349. IoInterfaceDirectory,
  350. Name,
  351. sizeof(Name),
  352. sizeof(INTERFACE_DIRECTORY),
  353. NULL,
  354. 0,
  355. DEVICE_INTERFACE_ALLOCATION_TAG);
  356. if (InterfaceDirectory == NULL) {
  357. Status = STATUS_NO_MEMORY;
  358. goto RegisterForInterfaceNotificationsEnd;
  359. }
  360. }
  361. ASSERT(InterfaceDirectory != NULL);
  362. //
  363. // Create the interface listener object.
  364. //
  365. InterfaceListener = ObCreateObject(ObjectInterfaceListener,
  366. InterfaceDirectory,
  367. NULL,
  368. 0,
  369. sizeof(INTERFACE_LISTENER),
  370. NULL,
  371. 0,
  372. DEVICE_INTERFACE_ALLOCATION_TAG);
  373. if (InterfaceListener == NULL) {
  374. Status = STATUS_INSUFFICIENT_RESOURCES;
  375. goto RegisterForInterfaceNotificationsEnd;
  376. }
  377. InterfaceListener->CallbackRoutine = CallbackRoutine;
  378. InterfaceListener->Device = Device;
  379. InterfaceListener->Context = Context;
  380. //
  381. // If the caller would like to be notified about existing interfaces,
  382. // notify them now.
  383. //
  384. if (NotifyForExisting != FALSE) {
  385. CurrentEntry = InterfaceDirectory->Header.ChildListHead.Next;
  386. while (CurrentEntry != &(InterfaceDirectory->Header.ChildListHead)) {
  387. CurrentInterface =
  388. (PDEVICE_INTERFACE_INSTANCE)LIST_VALUE(CurrentEntry,
  389. OBJECT_HEADER,
  390. SiblingEntry);
  391. CurrentEntry = CurrentEntry->Next;
  392. if (CurrentInterface->Header.Type != ObjectInterfaceInstance) {
  393. continue;
  394. }
  395. //
  396. // Notify the listener.
  397. //
  398. if ((Device == NULL) || (CurrentInterface->Device == Device)) {
  399. CallbackRoutine(InterfaceListener->Context,
  400. CurrentInterface->Device,
  401. CurrentInterface->InterfaceBuffer,
  402. CurrentInterface->InterfaceBufferSize,
  403. TRUE);
  404. }
  405. }
  406. }
  407. Status = STATUS_SUCCESS;
  408. RegisterForInterfaceNotificationsEnd:
  409. KeReleaseQueuedLock(IoInterfaceLock);
  410. if (InterfaceDirectory != NULL) {
  411. ObReleaseReference(InterfaceDirectory);
  412. }
  413. return Status;
  414. }
  415. KERNEL_API
  416. KSTATUS
  417. IoUnregisterForInterfaceNotifications (
  418. PUUID Interface,
  419. PINTERFACE_NOTIFICATION_CALLBACK CallbackRoutine,
  420. PDEVICE Device,
  421. PVOID Context
  422. )
  423. /*++
  424. Routine Description:
  425. This routine de-registers the given handler from receiving device interface
  426. notifications. Once this routine returns, the given handler will not
  427. receive notifications for the given interface.
  428. Arguments:
  429. Interface - Supplies a pointer to the UUID identifying the interface.
  430. CallbackRoutine - Supplies a pointer to the callback routine supplied on
  431. registration for notifications.
  432. Device - Supplies a pointer to the device supplied upon registration.
  433. Context - Supplies a pointer to the context supplied upon registration.
  434. Return Value:
  435. STATUS_SUCCESS on success.
  436. STATUS_INVALID_PARAMETER if an invalid interface or callback routine was
  437. supplied.
  438. STATUS_NOT_FOUND if no interface listener was found for the given callback
  439. routine on the given UUID.
  440. --*/
  441. {
  442. PLIST_ENTRY CurrentEntry;
  443. PINTERFACE_LISTENER CurrentListener;
  444. PINTERFACE_DIRECTORY InterfaceDirectory;
  445. CHAR Name[UUID_STRING_LENGTH + 1];
  446. KSTATUS Status;
  447. if ((Interface == NULL) || (CallbackRoutine == NULL)) {
  448. return STATUS_INVALID_PARAMETER;
  449. }
  450. IopPrintUuidToString(Name, UUID_STRING_LENGTH + 1, Interface);
  451. KeAcquireQueuedLock(IoInterfaceLock);
  452. //
  453. // Look up the interface directory. Create it if it doesn't exist.
  454. //
  455. InterfaceDirectory = ObFindObject(Name,
  456. UUID_STRING_LENGTH + 1,
  457. IoInterfaceDirectory);
  458. if (InterfaceDirectory == NULL) {
  459. Status = STATUS_NOT_FOUND;
  460. goto UnregisterForInterfaceNotificationsEnd;
  461. }
  462. //
  463. // Loop through the interface listeners searching for the one matching the
  464. // given callback routine.
  465. //
  466. Status = STATUS_NOT_FOUND;
  467. CurrentEntry = InterfaceDirectory->Header.ChildListHead.Next;
  468. while (CurrentEntry != &(InterfaceDirectory->Header.ChildListHead)) {
  469. CurrentListener = (PINTERFACE_LISTENER)LIST_VALUE(CurrentEntry,
  470. OBJECT_HEADER,
  471. SiblingEntry);
  472. CurrentEntry = CurrentEntry->Next;
  473. if (CurrentListener->Header.Type != ObjectInterfaceListener) {
  474. continue;
  475. }
  476. if ((CurrentListener->CallbackRoutine == CallbackRoutine) &&
  477. (CurrentListener->Device == Device) &&
  478. (CurrentListener->Context == Context)) {
  479. ObReleaseReference(CurrentListener);
  480. Status = STATUS_SUCCESS;
  481. break;
  482. }
  483. }
  484. UnregisterForInterfaceNotificationsEnd:
  485. if (InterfaceDirectory != NULL) {
  486. ObReleaseReference(InterfaceDirectory);
  487. }
  488. KeReleaseQueuedLock(IoInterfaceLock);
  489. return Status;
  490. }
  491. //
  492. // --------------------------------------------------------- Internal Functions
  493. //
  494. VOID
  495. IopNotifyInterfaceListeners (
  496. PINTERFACE_DIRECTORY InterfaceDirectory,
  497. PDEVICE_INTERFACE_INSTANCE InterfaceInstance,
  498. PDEVICE Device,
  499. BOOL Arrival
  500. )
  501. /*++
  502. Routine Description:
  503. This routine notifies all parties registered to receive device interface
  504. notifications. This routine MUST be called with the interface lock held.
  505. Arguments:
  506. InterfaceDirectory - Supplies a pointer to the interface undergoing the
  507. transition.
  508. InterfaceInstance - Supplies a pointer to the interface instance undergoing
  509. transition.
  510. Device - Supplies a pointer to the device changing its interface.
  511. Arrival - Supplies TRUE if the interface is arriving, or FALSE if it is
  512. departing.
  513. Return Value:
  514. None.
  515. --*/
  516. {
  517. PLIST_ENTRY CurrentEntry;
  518. PINTERFACE_LISTENER CurrentListener;
  519. CurrentEntry = InterfaceDirectory->Header.ChildListHead.Next;
  520. while (CurrentEntry != &(InterfaceDirectory->Header.ChildListHead)) {
  521. CurrentListener = (PINTERFACE_LISTENER)LIST_VALUE(CurrentEntry,
  522. OBJECT_HEADER,
  523. SiblingEntry);
  524. CurrentEntry = CurrentEntry->Next;
  525. if (CurrentListener->Header.Type != ObjectInterfaceListener) {
  526. continue;
  527. }
  528. ASSERT(CurrentListener->CallbackRoutine != NULL);
  529. if ((CurrentListener->Device == NULL) ||
  530. (Device == CurrentListener->Device)) {
  531. CurrentListener->CallbackRoutine(
  532. CurrentListener->Context,
  533. Device,
  534. InterfaceInstance->InterfaceBuffer,
  535. InterfaceInstance->InterfaceBufferSize,
  536. Arrival);
  537. }
  538. }
  539. return;
  540. }
  541. VOID
  542. IopPrintUuidToString (
  543. PSTR String,
  544. ULONG StringSize,
  545. PUUID Uuid
  546. )
  547. /*++
  548. Routine Description:
  549. This routine prints the given UUID out to a string.
  550. Arguments:
  551. String - Supplies a pointer to the string where the UUID will be written.
  552. StringSize - Supplies the size of the supplied string buffer.
  553. Uuid - Supplies a pointer to the UUID to print.
  554. Return Value:
  555. None.
  556. --*/
  557. {
  558. RtlPrintToString(String,
  559. StringSize,
  560. CharacterEncodingDefault,
  561. "%08X-%08X-%08X-%08X",
  562. Uuid->Data[0],
  563. Uuid->Data[1],
  564. Uuid->Data[2],
  565. Uuid->Data[3]);
  566. return;
  567. }