diff --git a/nx/include/switch/services/pdm.h b/nx/include/switch/services/pdm.h
index 9c0253b2..4fb8847d 100644
--- a/nx/include/switch/services/pdm.h
+++ b/nx/include/switch/services/pdm.h
@@ -6,7 +6,8 @@
  */
 #pragma once
 #include "../types.h"
-#include "../services/sm.h"
+#include "../sf/service.h"
+#include "../services/acc.h"
 #include "../kernel/event.h"
 
 /// PlayEventType
@@ -132,7 +133,7 @@ typedef struct {
 
 /// AccountEvent
 typedef struct {
-    union { u128 userID; } PACKED;    ///< userID.
+    AccountUid userID;                ///< \ref AccountUid
     u32 entryindex;                   ///< Entry index.
     u8 pad[4];                        ///< Padding.
     u64 timestampUser;                ///< See PdmPlayEvent::timestampUser.
@@ -182,10 +183,10 @@ Result pdmqryQueryPlayStatisticsByApplicationId(u64 titleID, PdmPlayStatistics *
 /**
  * @brief Gets \ref PdmPlayStatistics for the specified titleID and account userID.
  * @param[in] titleID Application titleID.
- * @param[in] userID Account userID.
+ * @param[in] userID \ref AccountUid
  * @param[out] stats \ref PdmPlayStatistics
  */
-Result pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(u64 titleID, u128 userID, PdmPlayStatistics *stats);
+Result pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(u64 titleID, AccountUid *userID, PdmPlayStatistics *stats);
 
 /**
  * @brief Gets \ref PdmLastPlayTime for the specified titles.
@@ -226,39 +227,39 @@ Result pdmqryQueryAccountEvent(u32 entryindex, PdmAccountEvent *events, s32 coun
  * @brief Gets a list of \ref PdmAccountPlayEvent.
  * @note Only available with [4.0.0+].
  * @param[in] entryindex Start entry index.
- * @param[in] userID Account userID.
+ * @param[in] userID \ref AccountUid
  * @param[out] events Output \ref PdmAccountPlayEvent array.
  * @param[in] count Max entries in the output array.
  * @param[out] total_out Total output entries.
  */
-Result pdmqryQueryAccountPlayEvent(u32 entryindex, u128 userID, PdmAccountPlayEvent *events, s32 count, s32 *total_out);
+Result pdmqryQueryAccountPlayEvent(u32 entryindex, AccountUid *userID, PdmAccountPlayEvent *events, s32 count, s32 *total_out);
 
 /**
  * @brief Gets range fields which can then be used with \ref pdmqryQueryAccountPlayEvent.
- * @param[in] userID Account userID.
+ * @param[in] userID \ref AccountUid
  * @param[out] total_entries Total entries.
  * @param[out] start_entryindex Start entry index.
  * @param[out] end_entryindex End entry index.
  */
-Result pdmqryGetAvailableAccountPlayEventRange(u128 userID, u32 *total_entries, u32 *start_entryindex, u32 *end_entryindex);
+Result pdmqryGetAvailableAccountPlayEventRange(AccountUid *userID, u32 *total_entries, u32 *start_entryindex, u32 *end_entryindex);
 
 /**
  * @brief Gets a list of titles played by the specified user.
  * @note Only available with [6.0.0+].
- * @param[in] userID Account userID.
+ * @param[in] userID \ref AccountUid
  * @param[out] titleIDs Output titleID array.
  * @param[in] count Max entries in the output array.
  * @param[out] total_out Total output entries.
  */
-Result pdmqryGetUserPlayedApplications(u128 userID, u64 *titleIDs, size_t count, u32 *total_out);
+Result pdmqryQueryRecentlyPlayedApplication(AccountUid *userID, u64 *titleIDs, size_t count, u32 *total_out);
 
 /**
  * @brief Gets an Event which is signaled when logging a new \ref PdmPlayEvent which would be available via \ref pdmqryQueryAccountEvent, where PdmPlayEvent::eventData::account::type is 0. 
  * @note Only available with [6.0.0+].
  * @note The Event must be closed by the user once finished with it.
- * @param[out] event_out Output Event with autoclear=false.
+ * @param[out] out_event Output Event with autoclear=false.
  */
-Result pdmqryGetUserAccountEvent(Event* event_out);
+Result pdmqryGetRecentlyPlayedApplicationUpdateEvent(Event* out_event);
 
 /**
  * @brief Helper function which converts a Play timestamp from the Pdm*Event structs to POSIX.
diff --git a/nx/source/services/pdm.c b/nx/source/services/pdm.c
index fac7823d..e9db6f2f 100644
--- a/nx/source/services/pdm.c
+++ b/nx/source/services/pdm.c
@@ -1,193 +1,75 @@
+#define NX_SERVICE_ASSUME_NON_DOMAIN
+#include "service_guard.h"
 #include <string.h>
-#include "types.h"
-#include "result.h"
-#include "arm/atomics.h"
-#include "kernel/ipc.h"
 #include "kernel/event.h"
-#include "services/sm.h"
 #include "services/pdm.h"
+#include "services/acc.h"
 #include "runtime/hosversion.h"
 
 static Service g_pdmqrySrv;
-static u64 g_pdmqryRefCnt;
 
-Result pdmqryInitialize(void) {
-    atomicIncrement64(&g_pdmqryRefCnt);
+NX_GENERATE_SERVICE_GUARD(pdmqry);
 
-    if (serviceIsActive(&g_pdmqrySrv))
-        return 0;
-
-    Result rc = smGetService(&g_pdmqrySrv, "pdm:qry");
-
-    if (R_FAILED(rc)) pdmqryExit();
-
-    return rc;
+Result _pdmqryInitialize(void) {
+    return smGetService(&g_pdmqrySrv, "pdm:qry");
 }
 
-void pdmqryExit(void) {
-    if (atomicDecrement64(&g_pdmqryRefCnt) == 0)
-        serviceClose(&g_pdmqrySrv);
+void _pdmqryCleanup(void) {
+    serviceClose(&g_pdmqrySrv);
 }
 
 Service* pdmqryGetServiceSession(void) {
     return &g_pdmqrySrv;
 }
 
-static Result _pdmqryQueryEvent(u64 cmd_id, u32 entryindex, void* events, size_t entrysize, s32 count, s32 *total_out) {
-    IpcCommand c;
-    ipcInitialize(&c);
+static Result _pdmCmdGetEvent(Service* srv, Event* out_event, bool autoclear, u32 cmd_id) {
+    Handle event = INVALID_HANDLE;
+    Result rc = serviceDispatch(srv, cmd_id,
+        .out_handle_attrs = { SfOutHandleAttr_HipcCopy },
+        .out_handles = &event,
+    );
 
-    ipcAddRecvBuffer(&c, events, count*entrysize, BufferType_Normal);
-
-    struct {
-        u64 magic;
-        u64 cmd_id;
-        u32 entryindex;
-    } *raw;
-
-    raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
-
-    raw->magic = SFCI_MAGIC;
-    raw->cmd_id = cmd_id;
-    raw->entryindex = entryindex;
-
-    Result rc = serviceIpcDispatch(&g_pdmqrySrv);
-
-    if (R_SUCCEEDED(rc)) {
-        IpcParsedCommand r;
-        struct {
-            u64 magic;
-            u64 result;
-            s32 total_out;
-        } *resp;
-
-        serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
-        resp = r.Raw;
-
-        rc = resp->result;
-
-        if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out;
-    }
+    if (R_SUCCEEDED(rc))
+        eventLoadRemote(out_event, event, autoclear);
 
     return rc;
 }
 
+static Result _pdmqryQueryEvent(u32 cmd_id, u32 entryindex, void* events, size_t entrysize, s32 count, s32 *total_out) {
+    return serviceDispatchInOut(&g_pdmqrySrv, cmd_id, entryindex, *total_out,
+        .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
+        .buffers = { { events, count*entrysize } },
+    );
+}
+
 Result pdmqryQueryApplicationEvent(u32 entryindex, PdmApplicationEvent *events, s32 count, s32 *total_out) {
     return _pdmqryQueryEvent(0, entryindex, events, sizeof(PdmApplicationEvent), count, total_out);
 }
 
 Result pdmqryQueryPlayStatisticsByApplicationId(u64 titleID, PdmPlayStatistics *stats) {
-    IpcCommand c;
-    ipcInitialize(&c);
-
-    struct {
-        u64 magic;
-        u64 cmd_id;
-        u64 titleID;
-    } *raw;
-
-    raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
-
-    raw->magic = SFCI_MAGIC;
-    raw->cmd_id = 4;
-    raw->titleID = titleID;
-
-    Result rc = serviceIpcDispatch(&g_pdmqrySrv);
-
-    if (R_SUCCEEDED(rc)) {
-        IpcParsedCommand r;
-        struct {
-            u64 magic;
-            u64 result;
-            PdmPlayStatistics stats;
-        } *resp;
-
-        serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
-        resp = r.Raw;
-
-        rc = resp->result;
-
-        if (R_SUCCEEDED(rc) && stats) memcpy(stats, &resp->stats, sizeof(resp->stats));
-    }
-
-    return rc;
+    return serviceDispatchInOut(&g_pdmqrySrv, 4, titleID, *stats);
 }
 
-Result pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(u64 titleID, u128 userID, PdmPlayStatistics *stats) {
-    IpcCommand c;
-    ipcInitialize(&c);
-
-    struct {
-        u64 magic;
-        u64 cmd_id;
+Result pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(u64 titleID, AccountUid *userID, PdmPlayStatistics *stats) {
+    const struct {
         u64 titleID;
-        union { u128 userID; } PACKED;
-    } *raw;
+        AccountUid userID;
+    } in = { titleID, *userID };
 
-    raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
-
-    raw->magic = SFCI_MAGIC;
-    raw->cmd_id = 5;
-    raw->titleID = titleID;
-    raw->userID = userID;
-
-    Result rc = serviceIpcDispatch(&g_pdmqrySrv);
-
-    if (R_SUCCEEDED(rc)) {
-        IpcParsedCommand r;
-        struct {
-            u64 magic;
-            u64 result;
-            PdmPlayStatistics stats;
-        } *resp;
-
-        serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
-        resp = r.Raw;
-
-        rc = resp->result;
-
-        if (R_SUCCEEDED(rc) && stats) memcpy(stats, &resp->stats, sizeof(resp->stats));
-    }
-
-    return rc;
+    return serviceDispatchInOut(&g_pdmqrySrv, 5, in, *stats);
 }
 
 Result pdmqryQueryLastPlayTime(PdmLastPlayTime *playtimes, const u64 *titleIDs, s32 count, s32 *total_out) {
-    IpcCommand c;
-    ipcInitialize(&c);
-
-    ipcAddSendBuffer(&c, titleIDs, count*sizeof(u64), BufferType_Normal);
-    ipcAddRecvBuffer(&c, playtimes, count*sizeof(PdmLastPlayTime), BufferType_Normal);
-
-    struct {
-        u64 magic;
-        u64 cmd_id;
-    } *raw;
-
-    raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
-
-    raw->magic = SFCI_MAGIC;
-    raw->cmd_id = 7;
-
-    Result rc = serviceIpcDispatch(&g_pdmqrySrv);
-
-    if (R_SUCCEEDED(rc)) {
-        IpcParsedCommand r;
-        struct {
-            u64 magic;
-            u64 result;
-            s32 total_out;
-        } *resp;
-
-        serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
-        resp = r.Raw;
-
-        rc = resp->result;
-
-        if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out;
-    }
-
-    return rc;
+    return serviceDispatchOut(&g_pdmqrySrv, 7, *total_out,
+        .buffer_attrs = {
+            SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
+            SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
+        },
+        .buffers = {
+            { playtimes, count*sizeof(PdmLastPlayTime) },
+            { titleIDs, count*sizeof(u64) },
+        },
+    );
 }
 
 Result pdmqryQueryPlayEvent(u32 entryindex, PdmPlayEvent *events, s32 count, s32 *total_out) {
@@ -195,41 +77,18 @@ Result pdmqryQueryPlayEvent(u32 entryindex, PdmPlayEvent *events, s32 count, s32
 }
 
 Result pdmqryGetAvailablePlayEventRange(u32 *total_entries, u32 *start_entryindex, u32 *end_entryindex) {
-    IpcCommand c;
-    ipcInitialize(&c);
-
     struct {
-        u64 magic;
-        u64 cmd_id;
-    } *raw;
-
-    raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
-
-    raw->magic = SFCI_MAGIC;
-    raw->cmd_id = 9;
-
-    Result rc = serviceIpcDispatch(&g_pdmqrySrv);
+        u32 total_entries;
+        u32 start_entryindex;
+        u32 end_entryindex;
+    } out;
 
+    Result rc = serviceDispatchOut(&g_pdmqrySrv, 9, out);
     if (R_SUCCEEDED(rc)) {
-        IpcParsedCommand r;
-        struct {
-            u64 magic;
-            u64 result;
-            u32 total_entries;
-            u32 start_entryindex;
-            u32 end_entryindex;
-        } *resp;
-
-        serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
-        resp = r.Raw;
-
-        rc = resp->result;
-
-        if (R_SUCCEEDED(rc) && total_entries) *total_entries = resp->total_entries;
-        if (R_SUCCEEDED(rc) && start_entryindex) *start_entryindex = resp->start_entryindex;
-        if (R_SUCCEEDED(rc) && end_entryindex) *end_entryindex = resp->end_entryindex;
+        if (total_entries) *total_entries = out.total_entries;
+        if (start_entryindex) *start_entryindex = out.start_entryindex;
+        if (end_entryindex) *end_entryindex = out.end_entryindex;
     }
-
     return rc;
 }
 
@@ -237,173 +96,54 @@ Result pdmqryQueryAccountEvent(u32 entryindex, PdmAccountEvent *events, s32 coun
     return _pdmqryQueryEvent(10, entryindex, events, sizeof(PdmAccountEvent), count, total_out);
 }
 
-Result pdmqryQueryAccountPlayEvent(u32 entryindex, u128 userID, PdmAccountPlayEvent *events, s32 count, s32 *total_out) {
-    IpcCommand c;
-    ipcInitialize(&c);
-
+Result pdmqryQueryAccountPlayEvent(u32 entryindex, AccountUid *userID, PdmAccountPlayEvent *events, s32 count, s32 *total_out) {
     if (hosversionBefore(4,0,0))
         return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
 
-    ipcAddRecvBuffer(&c, events, count*sizeof(PdmAccountPlayEvent), BufferType_Normal);
-
-    struct {
-        u64 magic;
-        u64 cmd_id;
+    const struct {
         u32 entryindex;
-        u32 pad;
-        union { u128 userID; } PACKED;
-    } *raw;
+        AccountUid userID;
+    } in = { entryindex, *userID };
 
-    raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
-
-    raw->magic = SFCI_MAGIC;
-    raw->cmd_id = 11;
-    raw->entryindex = entryindex;
-    raw->userID = userID;
-
-    Result rc = serviceIpcDispatch(&g_pdmqrySrv);
-
-    if (R_SUCCEEDED(rc)) {
-        IpcParsedCommand r;
-        struct {
-            u64 magic;
-            u64 result;
-            s32 total_out;
-        } *resp;
-
-        serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
-        resp = r.Raw;
-
-        rc = resp->result;
-
-        if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out;
-    }
-
-    return rc;
+    return serviceDispatchInOut(&g_pdmqrySrv, 11, in, *total_out,
+        .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
+        .buffers = { { events, count*sizeof(PdmAccountPlayEvent) } },
+    );
 }
 
-Result pdmqryGetAvailableAccountPlayEventRange(u128 userID, u32 *total_entries, u32 *start_entryindex, u32 *end_entryindex) {
-    IpcCommand c;
-    ipcInitialize(&c);
-
+Result pdmqryGetAvailableAccountPlayEventRange(AccountUid *userID, u32 *total_entries, u32 *start_entryindex, u32 *end_entryindex) {
     if (hosversionBefore(4,0,0))
         return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
 
     struct {
-        u64 magic;
-        u64 cmd_id;
-        u128 userID;
-    } *raw;
-
-    raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
-
-    raw->magic = SFCI_MAGIC;
-    raw->cmd_id = 12;
-    raw->userID = userID;
-
-    Result rc = serviceIpcDispatch(&g_pdmqrySrv);
+        u32 total_entries;
+        u32 start_entryindex;
+        u32 end_entryindex;
+    } out;
 
+    Result rc = serviceDispatchInOut(&g_pdmqrySrv, 12, *userID, out);
     if (R_SUCCEEDED(rc)) {
-        IpcParsedCommand r;
-        struct {
-            u64 magic;
-            u64 result;
-            u32 total_entries;
-            u32 start_entryindex;
-            u32 end_entryindex;
-        } *resp;
-
-        serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
-        resp = r.Raw;
-
-        rc = resp->result;
-
-        if (R_SUCCEEDED(rc) && total_entries) *total_entries = resp->total_entries;
-        if (R_SUCCEEDED(rc) && start_entryindex) *start_entryindex = resp->start_entryindex;
-        if (R_SUCCEEDED(rc) && end_entryindex) *end_entryindex = resp->end_entryindex;
+        if (total_entries) *total_entries = out.total_entries;
+        if (start_entryindex) *start_entryindex = out.start_entryindex;
+        if (end_entryindex) *end_entryindex = out.end_entryindex;
     }
-
     return rc;
 }
 
-Result pdmqryGetUserPlayedApplications(u128 userID, u64 *titleIDs, size_t count, u32 *total_out) {
-    IpcCommand c;
-    ipcInitialize(&c);
-
+Result pdmqryQueryRecentlyPlayedApplication(AccountUid *userID, u64 *titleIDs, size_t count, u32 *total_out) {
     if (hosversionBefore(6,0,0))
         return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
 
-    ipcAddRecvBuffer(&c, titleIDs, count*sizeof(u64), BufferType_Normal);
-
-    struct {
-        u64 magic;
-        u64 cmd_id;
-        u128 userID;
-    } *raw;
-
-    raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
-
-    raw->magic = SFCI_MAGIC;
-    raw->cmd_id = 14;
-    raw->userID = userID;
-
-    Result rc = serviceIpcDispatch(&g_pdmqrySrv);
-
-    if (R_SUCCEEDED(rc)) {
-        IpcParsedCommand r;
-        struct {
-            u64 magic;
-            u64 result;
-            u32 total_out;
-        } *resp;
-
-        serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
-        resp = r.Raw;
-
-        rc = resp->result;
-
-        if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out;
-    }
-
-    return rc;
+    return serviceDispatchInOut(&g_pdmqrySrv, 14, *userID, *total_out,
+        .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
+        .buffers = { { titleIDs, count*sizeof(u64) } },
+    );
 }
 
-Result pdmqryGetUserAccountEvent(Event* event_out) {
-    IpcCommand c;
-    ipcInitialize(&c);
-
+Result pdmqryGetRecentlyPlayedApplicationUpdateEvent(Event* out_event) {
     if (hosversionBefore(6,0,0))
         return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
 
-    struct {
-        u64 magic;
-        u64 cmd_id;
-    } *raw;
-
-    raw = serviceIpcPrepareHeader(&g_pdmqrySrv, &c, sizeof(*raw));
-
-    raw->magic = SFCI_MAGIC;
-    raw->cmd_id = 15;
-
-    Result rc = serviceIpcDispatch(&g_pdmqrySrv);
-
-    if (R_SUCCEEDED(rc)) {
-        IpcParsedCommand r;
-        struct {
-            u64 magic;
-            u64 result;
-        } *resp;
-
-        serviceIpcParse(&g_pdmqrySrv, &r, sizeof(*resp));
-        resp = r.Raw;
-
-        rc = resp->result;
-
-        if (R_SUCCEEDED(rc)) {
-            eventLoadRemote(event_out, r.Handles[0], false);
-        }
-    }
-
-    return rc;
+    return _pdmCmdGetEvent(&g_pdmqrySrv, out_event, false, 15);
 }