*/
typedef struct _XENBUS_STORE_WATCH XENBUS_STORE_WATCH, *PXENBUS_STORE_WATCH;
+/*! \typedef XENBUS_STORE_PERMISSION_MASK
+ \brief Bitmask of XenStore key permissions
+*/
+typedef enum _XENBUS_STORE_PERMISSION_MASK {
+ XENBUS_STORE_PERM_NONE = 0,
+ XENBUS_STORE_PERM_READ = 1,
+ XENBUS_STORE_PERM_WRITE = 2,
+} XENBUS_STORE_PERMISSION_MASK;
+
+/*! \typedef XENBUS_STORE_PERMISSION
+ \brief XenStore key permissions entry for a single domain
+*/
+typedef struct _XENBUS_STORE_PERMISSION {
+ USHORT Domain;
+ XENBUS_STORE_PERMISSION_MASK Mask;
+} XENBUS_STORE_PERMISSION, *PXENBUS_STORE_PERMISSION;
+
/*! \typedef XENBUS_STORE_ACQUIRE
\brief Acquire a reference to the STORE interface
IN PINTERFACE Interface
);
+/*! \typedef XENBUS_STORE_PERMISSIONS_SET
+ \brief Set permissions for a XenStore key
+
+ \param Interface The interface header
+ \param Transaction The transaction handle (NULL if this is not
+ part of a transaction)
+ \param Prefix An optional prefix for the \a Node
+ \param Node The concatenation of the \a Prefix and this value specifies
+ the XenStore key to set permissions of
+ \param Permissions An array of permissions to set
+ \param NumberPermissions Number of elements in the \a Permissions array
+*/
+typedef NTSTATUS
+(*XENBUS_STORE_PERMISSIONS_SET)(
+ IN PINTERFACE Interface,
+ IN PXENBUS_STORE_TRANSACTION Transaction OPTIONAL,
+ IN PCHAR Prefix OPTIONAL,
+ IN PCHAR Node,
+ IN PXENBUS_STORE_PERMISSION Permissions,
+ IN ULONG NumberPermissions
+ );
+
// {86824C3B-D34E-4753-B281-2F1E3AD214D7}
DEFINE_GUID(GUID_XENBUS_STORE_INTERFACE,
0x86824c3b, 0xd34e, 0x4753, 0xb2, 0x81, 0x2f, 0x1e, 0x3a, 0xd2, 0x14, 0xd7);
+/*! \struct _XENBUS_STORE_INTERFACE_V1
+ \brief STORE interface version 1
+ \ingroup interfaces
+*/
struct _XENBUS_STORE_INTERFACE_V1 {
INTERFACE Interface;
XENBUS_STORE_ACQUIRE StoreAcquire;
XENBUS_STORE_POLL StorePoll;
};
-/*! \struct _XENBUS_STORE_INTERFACE_V1
- \brief STORE interface version 1
+/*! \struct _XENBUS_STORE_INTERFACE_V2
+ \brief STORE interface version 2
\ingroup interfaces
*/
-typedef struct _XENBUS_STORE_INTERFACE_V1 XENBUS_STORE_INTERFACE, *PXENBUS_STORE_INTERFACE;
+struct _XENBUS_STORE_INTERFACE_V2 {
+ INTERFACE Interface;
+ XENBUS_STORE_ACQUIRE StoreAcquire;
+ XENBUS_STORE_RELEASE StoreRelease;
+ XENBUS_STORE_FREE StoreFree;
+ XENBUS_STORE_READ StoreRead;
+ XENBUS_STORE_PRINTF StorePrintf;
+ XENBUS_STORE_PERMISSIONS_SET StorePermissionsSet;
+ XENBUS_STORE_REMOVE StoreRemove;
+ XENBUS_STORE_DIRECTORY StoreDirectory;
+ XENBUS_STORE_TRANSACTION_START StoreTransactionStart;
+ XENBUS_STORE_TRANSACTION_END StoreTransactionEnd;
+ XENBUS_STORE_WATCH_ADD StoreWatchAdd;
+ XENBUS_STORE_WATCH_REMOVE StoreWatchRemove;
+ XENBUS_STORE_POLL StorePoll;
+};
+
+typedef struct _XENBUS_STORE_INTERFACE_V2 XENBUS_STORE_INTERFACE, *PXENBUS_STORE_INTERFACE;
/*! \def XENBUS_STORE
\brief Macro at assist in method invocation
#endif // _WINDLL
#define XENBUS_STORE_INTERFACE_VERSION_MIN 1
-#define XENBUS_STORE_INTERFACE_VERSION_MAX 1
+#define XENBUS_STORE_INTERFACE_VERSION_MAX 2
#endif // _XENBUS_STORE_INTERFACE_H
case XS_RELEASE:
case XS_GET_DOMAIN_PATH:
case XS_MKDIR:
- case XS_SET_PERMS:
case XS_IS_DOMAIN_INTRODUCED:
case XS_RESUME:
case XS_SET_TARGET:
Header->type != XS_TRANSACTION_END &&
Header->type != XS_WRITE &&
Header->type != XS_RM &&
+ Header->type != XS_SET_PERMS &&
Header->type != XS_WATCH_EVENT &&
Header->type != XS_ERROR &&
!StoreIgnoreHeaderType(Header->type)) {
Response->Header.type == XS_ERROR ||
Response->Header.type == Request->Header.type);
- RtlZeroMemory(Request, sizeof(XENBUS_STORE_REQUEST));
+ RtlZeroMemory(Request, sizeof (XENBUS_STORE_REQUEST));
KeLowerIrql(Irql);
KeReleaseSpinLockFromDpcLevel(&Context->Lock);
}
+static NTSTATUS
+StorePermissionToString(
+ IN PXENBUS_STORE_PERMISSION Permission,
+ OUT PCHAR Buffer,
+ IN ULONG BufferSize,
+ OUT PULONG UsedSize
+ )
+{
+ size_t Remaining;
+ NTSTATUS status;
+
+ ASSERT(BufferSize > 1);
+
+ switch (Permission->Mask) {
+ case XENBUS_STORE_PERM_NONE:
+ *Buffer = 'n';
+ break;
+
+ case XENBUS_STORE_PERM_READ:
+ *Buffer = 'r';
+ break;
+
+ case XENBUS_STORE_PERM_WRITE:
+ *Buffer = 'w';
+ break;
+
+ case XENBUS_STORE_PERM_READ | XENBUS_STORE_PERM_WRITE:
+ *Buffer = 'b';
+ break;
+
+ default:
+ status = STATUS_INVALID_PARAMETER;
+ goto fail1;
+ }
+
+ status = RtlStringCbPrintfExA(Buffer + 1,
+ BufferSize - 1,
+ NULL,
+ &Remaining,
+ 0,
+ "%u",
+ Permission->Domain);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
+ *UsedSize = BufferSize - (ULONG)Remaining + 1;
+
+ return STATUS_SUCCESS;
+
+fail2:
+ Error("fail2\n");
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+static NTSTATUS
+StorePermissionsSet(
+ IN PINTERFACE Interface,
+ IN PXENBUS_STORE_TRANSACTION Transaction OPTIONAL,
+ IN PCHAR Prefix OPTIONAL,
+ IN PCHAR Node,
+ IN PXENBUS_STORE_PERMISSION Permissions,
+ IN ULONG NumberPermissions
+ )
+{
+ PXENBUS_STORE_CONTEXT Context = Interface->Context;
+ XENBUS_STORE_REQUEST Request;
+ PXENBUS_STORE_RESPONSE Response;
+ NTSTATUS status;
+ ULONG Index;
+ ULONG Length;
+ ULONG Used;
+ PCHAR Path;
+ PCHAR PermissionString;
+ PCHAR Segment;
+
+ PermissionString = __StoreAllocate(XENSTORE_PAYLOAD_MAX);
+
+ status = STATUS_NO_MEMORY;
+ if (PermissionString == NULL)
+ goto fail1;
+
+ if (Prefix == NULL)
+ Length = (ULONG)strlen(Node) + sizeof (CHAR);
+ else
+ Length = (ULONG)strlen(Prefix) + 1 + (ULONG)strlen(Node) + sizeof (CHAR);
+
+ Path = __StoreAllocate(Length);
+
+ if (Path == NULL)
+ goto fail2;
+
+ status = (Prefix == NULL) ?
+ RtlStringCbPrintfA(Path, Length, "%s", Node) :
+ RtlStringCbPrintfA(Path, Length, "%s/%s", Prefix, Node);
+ ASSERT(NT_SUCCESS(status));
+
+ RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
+
+ for (Index = 0, Segment = PermissionString, Length = XENSTORE_PAYLOAD_MAX;
+ Index < NumberPermissions;
+ Index++) {
+ status = StorePermissionToString(&Permissions[Index],
+ Segment,
+ Length,
+ &Used);
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
+ Segment += Used;
+ Length -= Used;
+ }
+
+ status = StorePrepareRequest(Context,
+ &Request,
+ Transaction,
+ XS_SET_PERMS,
+ Path, strlen(Path),
+ "", 1,
+ PermissionString, XENSTORE_PAYLOAD_MAX - Length,
+ NULL, 0);
+ if (!NT_SUCCESS(status))
+ goto fail4;
+
+ Response = StoreSubmitRequest(Context, &Request);
+
+ status = STATUS_NO_MEMORY;
+ if (Response == NULL)
+ goto fail5;
+
+ status = StoreCheckResponse(Response);
+ if (!NT_SUCCESS(status))
+ goto fail6;
+
+ StoreFreeResponse(Response);
+ ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
+
+ __StoreFree(Path);
+ __StoreFree(PermissionString);
+
+ return STATUS_SUCCESS;
+
+fail6:
+ Error("fail6\n");
+ StoreFreeResponse(Response);
+
+fail5:
+ Error("fail5\n");
+
+fail4:
+ Error("fail4\n");
+
+fail3:
+ Error("fail3\n");
+
+ __StoreFree(Path);
+ ASSERT(IsZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST)));
+
+fail2:
+ Error("fail2\n");
+
+ __StoreFree(PermissionString);
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
static
_Function_class_(KSERVICE_ROUTINE)
_IRQL_requires_(HIGH_LEVEL)
StorePoll
};
+static struct _XENBUS_STORE_INTERFACE_V2 StoreInterfaceVersion2 = {
+ { sizeof (struct _XENBUS_STORE_INTERFACE_V2), 2, NULL, NULL, NULL },
+ StoreAcquire,
+ StoreRelease,
+ StoreFree,
+ StoreRead,
+ StorePrintf,
+ StorePermissionsSet,
+ StoreRemove,
+ StoreDirectory,
+ StoreTransactionStart,
+ StoreTransactionEnd,
+ StoreWatchAdd,
+ StoreWatchRemove,
+ StorePoll
+};
+
NTSTATUS
StoreInitialize(
IN PXENBUS_FDO Fdo,
status = STATUS_SUCCESS;
break;
}
+ case 2: {
+ struct _XENBUS_STORE_INTERFACE_V2 *StoreInterface;
+
+ StoreInterface = (struct _XENBUS_STORE_INTERFACE_V2 *)Interface;
+
+ status = STATUS_BUFFER_OVERFLOW;
+ if (Size < sizeof (struct _XENBUS_STORE_INTERFACE_V2))
+ break;
+
+ *StoreInterface = StoreInterfaceVersion2;
+
+ ASSERT3U(Interface->Version, == , Version);
+ Interface->Context = Context;
+
+ status = STATUS_SUCCESS;
+ break;
+ }
default:
status = STATUS_NOT_SUPPORTED;
break;