Advanced
Single-page view · as markdown
Private hives and layers
Peios / Using Peios / Advanced
Everything in the core topic describes one shared registry that every process sees the same way (subject to access control). Private hives and private layers relax that: they let a particular caller see a registry that differs from everyone else's — the building block for sandboxing and container-style isolation.
This is an advanced feature, and a partly forward-looking one. The registry defines how a private hive or layer participates in resolution; but who is allowed to see one is decided by a thread's credentials, and that credential model is part of KACS and not yet fully specified. Treat this page as the shape of the feature, not a how-to.
Private hives #
A private hive is a hive that is visible only to threads whose credentials carry a matching scope — an opaque identity that marks "you are allowed to see this hive". To everyone else it does not exist.
The powerful case is shadowing. A private hive can take the same name as a global one — Machine\, say — and for a thread that carries the scope, the private hive is what Machine\ resolves to, not the global one. A sandboxed process can therefore be given an entirely separate Machine\ while every other process continues to see the real one, with no change to the paths anyone uses. That is complete registry isolation without a parallel namespace: same paths, different contents, decided by who is asking.
Private layers #
A private layer is a layer that is globally disabled — invisible in normal resolution — but attached to a specific thread's credentials. For that thread, and only that thread, the layer is treated as active and competes in the per-value contest at its precedence exactly like any other layer. Everyone else resolves as if it were not there.
This is the lighter-weight tool, for when you want a different value here and there rather than a whole separate hive:
- Per-session overrides — run one application with experimental settings without disturbing other sessions.
- Testing — inject configuration for one process without writing it into the shared registry.
- Sandboxing — give a confined process a slightly different view without standing up a private hive.
Private layers are per thread, not per process: because the attachment rides on a thread's credentials, different threads in the same process can carry different private layers (for instance, a service thread acting on behalf of a particular client). The number a thread can carry is bounded.
Authorisation lives in KACS #
The registry defines only the resolution behaviour — private hives are checked ahead of global ones, and a thread's private layers fold into its contests. The decision about whether a thread may join a scope or attach a layer belongs to KACS's credential model. One constraint is already clear and worth stating: attaching a layer that sits above others in precedence must be privileged, or an unprivileged process could attach an existing high-precedence policy layer to itself and gain a window onto configuration it should not see or influence. The isolation is only as strong as the rule that decides who may carry a scope or a private layer.
Where to go next #
For the resolution model these build on — precedence, recency, and the per-value contest — read Layers.
For where private hives are routed and served, read LCS and sources.
Transactions
Peios / Using Peios / Advanced
Most registry writes stand alone. But sometimes a set of changes only makes sense together — a role's keys and values are one coherent configuration, and a half-written version would be worse than none at all. A transaction makes several writes atomic: all of them commit, or none do. This is a developer-facing feature — you reach for it when writing to the registry, not when operating a running system — which is why it sits among the advanced topics.
Transactions, in one sentence #
A transaction groups many registry writes into one all-or-nothing commit, so other readers only ever see the complete change, never a partial one.
All or nothing #
Inside a transaction you perform a series of writes and then commit. At commit, they all take effect together. If you abort instead — or the process dies, or the transaction sits open too long and times out — none of them take effect. There is no partial application.
External readers see only committed state. Until you commit, your in-progress writes are invisible to everyone else; the instant you commit, the whole set appears at once. A service reading configuration never catches a transaction halfway. Within your own transaction you do see your own pending writes, so you can write a value and read it back before committing.
The canonical use: installing a role #
This is why role installation is clean. A role's entire configuration — its keys, its values, its layer — is written inside one transaction and committed as a unit. The role is never observed half-installed: either the whole role is there or none of it is. (Removing a role is the other mechanism — deleting its layer — covered with layers.)
Any consistent multi-key update wants the same treatment: change several related settings as one atomic step, rather than letting readers see an inconsistent in-between.
Limits worth knowing #
- One store at a time. A transaction is scoped to a single hive's store; it cannot span hives backed by different sources. Atomicity across separate stores is not offered.
- No nesting. Transactions are flat — there are no sub-transactions or savepoints.
- Bounded lifetime. An open transaction holds a write position, so it cannot be left open indefinitely; if it is not committed in time it is aborted automatically. This stops a stalled or abandoned writer from blocking everyone else's writes to that store.
- Abandonment is safe. Closing the handle without committing aborts cleanly, and a process dying does the same — there are no orphaned transactions left holding things up.
Transactions and layers #
A transaction provides atomicity; it is not a layer and it does not change which write wins. The two compose: a role install uses a transaction to apply its writes atomically and a layer to make them removable later. Keep them distinct — atomicity is "all together", layering is "which one wins, and how to revert".
Transactions are not conflict-detected at the value level. If two committed transactions wrote the same value, both succeed, and the usual rule settles it: the more recent write wins, exactly as in layer resolution. A transaction guarantees its own writes land together; it does not lock anyone else out of the values it touched. (For the case where you must not clobber a concurrent change, a conditional write lets a single write proceed only if the value has not changed since you read it.)
Where to go next #
For how a role uses a transaction and a layer together, read What layers are for.
For the recency rule that settles competing writes, read Layers.
Registry links
Peios / Using Peios / Advanced
A registry key can be a symbolic link to another key. Open a link key by its path and the registry follows it through to the target, handing you a handle on the target key. Links let one part of the namespace point at another, the way a filesystem symlink does.
Links are an advanced feature with a small, sharp set of rules, and they are the one exception to a property the rest of the topic relies on.
A link is a flag plus a target value #
Two pieces make a link, and both are needed:
- The key is marked as a link when it is created. This is a fixed property of the key.
- The key's default value, of type
REG_LINK, holds the target path — an absolute registry path the link points at.
When path resolution reaches a link key, the registry reads that target and continues resolving from there; the handle you get back refers to the target, not the link.
The one place the registry reads a value #
Keys, values, and types made a point of it: the registry stores a value's type and bytes but never interprets them. REG_LINK is the single exception. It is the one type the registry acts on itself — following it during path resolution — rather than handing it back untouched. Everything else remains opaque; links are the lone case where the store cares what a value says.
Managing the link itself #
Normally you want to follow a link. To operate on the link key itself — to change where it points or delete it — you open it with a flag that says "open the link, do not follow it". Without that flag every open lands on the target, which would make the link impossible to manage.
Creating a link is privileged #
Because a link silently redirects whoever opens it, creating one is restricted. It requires the KEY_CREATE_LINK right on the parent and a privileged caller (the system-trust privilege, or Administrator membership). A link is a small piece of trusted plumbing, not something an ordinary process gets to introduce into a path other callers will traverse.
There is one safety rule worth knowing: a link target is followed literally, and the CurrentUser\ convenience alias is not expanded inside it. This stops a link from redirecting a privileged service that resolves CurrentUser\ into the service's own user hive — a classic confused-deputy trap. Link targets route by their literal hive name. Resolution is also bounded by a hop limit, so a cycle of links fails rather than looping forever.
Layers can redirect a link #
The target is an ordinary layered value — the link key's default value — so it plays by the same rules as any other value. A higher-precedence or more-recent layer can write a different REG_LINK target and redirect the link; remove that layer and the original target resurfaces, by the usual automatic revert. And if a layer writes a default value that is not a REG_LINK onto a key that is still flagged as a link, resolution through it fails until the offending layer is removed or overridden. The link's identity is fixed at creation; its target is just configuration, and configuration is layered.
Where to go next #
For the opaque-value rule this is the exception to, read Keys, values, and types.
For how a layer can redirect or break a link, read Layers.