From e7e6bb45b68a2a7bd3d0203138d76b4d2b8ff602 Mon Sep 17 00:00:00 2001
From: Jiri Formacek <jiri.formacek@hotmail.com>
Date: Sat, 26 Dec 2020 13:35:09 +0100
Subject: [PATCH] New transforms and enhanced transform loading

---
 S.DS.P.psm1                       |  4 +-
 Transforms/Integer.ps1            |  2 +-
 Transforms/quotaUsage.ps1         | 42 ++++++++++++++++++++
 Transforms/searchFlags.ps1        | 65 +++++++++++++++++++++++++++++++
 Transforms/securityDescriptor.ps1 |  2 +-
 Transforms/systemFlags.ps1        | 65 +++++++++++++++++++++++++++++++
 6 files changed, 176 insertions(+), 4 deletions(-)
 create mode 100644 Transforms/quotaUsage.ps1
 create mode 100644 Transforms/searchFlags.ps1
 create mode 100644 Transforms/systemFlags.ps1

diff --git a/S.DS.P.psm1 b/S.DS.P.psm1
index e0433a7..a44a8e1 100644
--- a/S.DS.P.psm1
+++ b/S.DS.P.psm1
@@ -1244,7 +1244,7 @@ More about attribute transforms and how to create them: https://github.com/jform
 
     [CmdletBinding()]
     param (
-        [Parameter(Mandatory,ParameterSetName='Name')]
+        [Parameter(Mandatory,ParameterSetName='Name', Position=0)]
         [string]
             #Name of the transform
         $Name,
@@ -1253,7 +1253,7 @@ More about attribute transforms and how to create them: https://github.com/jform
             #Name of the attribute that will be processed by transform
             #If not specified, transform will be registered on all supported attributes
         $AttributeName,
-        [Parameter(Mandatory,ValueFromPipeline,ParameterSetName='TransformObject')]
+        [Parameter(Mandatory,ValueFromPipeline,ParameterSetName='TransformObject', Position=0)]
         [PSCustomObject]
         $Transform
     )
diff --git a/Transforms/Integer.ps1 b/Transforms/Integer.ps1
index b0abf5b..ce6295f 100644
--- a/Transforms/Integer.ps1
+++ b/Transforms/Integer.ps1
@@ -13,7 +13,7 @@ if($FullLoad)
 }
 
 #add attributes that can be used with this transform
-$SupportedAttributes = @('msDS-Approx-Immed-Subordinates','codePage','countryCode','logonCount')
+$SupportedAttributes = @('codePage','countryCode','logonCount','msDS-Approx-Immed-Subordinates','ms-DS-KeyVersionNumber','ms-DS-ManagedPasswordInterval')
 
 # This is mandatory definition of transform that is expected by transform architecture
 $prop=[Ordered]@{
diff --git a/Transforms/quotaUsage.ps1 b/Transforms/quotaUsage.ps1
new file mode 100644
index 0000000..8f676ef
--- /dev/null
+++ b/Transforms/quotaUsage.ps1
@@ -0,0 +1,42 @@
+
+[CmdletBinding()]
+param (
+    [Parameter()]
+    [Switch]
+    $FullLoad
+)
+
+$codeBlock=[PSCustomObject][Ordered]@{
+    SupportedAttributes=@('msDS-TopQuotaUsage')
+    OnLoad = $null
+    OnSave = $null
+}
+
+$codeBlock.OnLoad = { 
+    param(
+    [string[]]$Values
+    )
+    Process
+    {
+        foreach($Value in $Values)
+        {
+            [xml]$Value.SubString(0,$Value.Length-2)
+        }
+    }
+}
+$codeBlock.OnSave = { 
+    param(
+    [object[]]$Values
+    )
+    
+    Process
+    {
+        foreach($Value in $Values)
+        {
+            $Value.InnerXml
+        }
+    }
+}
+
+$codeBlock
+
diff --git a/Transforms/searchFlags.ps1 b/Transforms/searchFlags.ps1
new file mode 100644
index 0000000..9db3b1d
--- /dev/null
+++ b/Transforms/searchFlags.ps1
@@ -0,0 +1,65 @@
+[CmdletBinding()]
+param (
+    [Parameter()]
+    [Switch]
+    $FullLoad
+)
+
+if($FullLoad)
+{
+# From [MS-ADTS]/2.2.9
+# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/7c1cdf82-1ecc-4834-827e-d26ff95fb207
+Add-Type @'
+using System;
+[Flags]
+public enum SearchFlags
+{
+    ATTINDEX =          0x1,
+    PDNTATTINDEX =      0x2,
+    ANR =               0x4,
+    PRESERVEONDELETE =  0x8,
+    COPY =              0x10,
+    TUPLEINDEX =        0x20,
+    SUBTREEATTINDEX =   0x40,
+    CONFIDENTIAL =      0x80,
+    NEVERVALUEAUDIT =   0x100,
+    RODCFilteredAttribute = 0x200,
+    EXTENDEDLINKTRACKING =  0x400,
+    BASEONLY =              0x800,
+    PARTITIONSECRET =       0x1000,
+}
+'@
+}
+
+$codeBlock=[PSCustomObject][Ordered]@{
+    SupportedAttributes=@('searchFlags')
+    OnLoad = $null
+    OnSave = $null
+}
+$codeBlock.OnLoad = { 
+    param(
+    [object[]]$Values
+    )
+    Process
+    {
+        foreach($Value in $Values)
+        {
+            [SearchFlags].GetEnumValues().ForEach({if((([int32]$Value) -band $_) -eq $_) {"$_"}})
+        }
+    }
+}
+$codeBlock.OnSave = { 
+    param(
+    [object[]]$Values
+    )
+    
+    Process
+    {
+        $retVal = 0
+        $Values.ForEach({ [SearchFlags]$val=$_; $retVal+=$val})
+        $retVal
+ 
+    }
+}
+$codeBlock
+
diff --git a/Transforms/securityDescriptor.ps1 b/Transforms/securityDescriptor.ps1
index ac668a2..aa81db5 100644
--- a/Transforms/securityDescriptor.ps1
+++ b/Transforms/securityDescriptor.ps1
@@ -11,7 +11,7 @@ if($FullLoad)
 
 $prop=[Ordered]@{
     BinaryInput=$true
-    SupportedAttributes=@('ntSecurityDescriptor','msDS-AllowedToActOnBehalfOfOtherIdentity')
+    SupportedAttributes=@('msDS-AllowedToActOnBehalfOfOtherIdentity','ms-DS-GroupMSAMembership','ntSecurityDescriptor')
     OnLoad = $null
     OnSave = $null
 }
diff --git a/Transforms/systemFlags.ps1 b/Transforms/systemFlags.ps1
new file mode 100644
index 0000000..5a43a1b
--- /dev/null
+++ b/Transforms/systemFlags.ps1
@@ -0,0 +1,65 @@
+[CmdletBinding()]
+param (
+    [Parameter()]
+    [Switch]
+    $FullLoad
+)
+
+if($FullLoad)
+{
+# From [MS-ADTS]/2.2.10
+# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/1e38247d-8234-4273-9de3-bbf313548631
+Add-Type @'
+using System;
+[Flags]
+public enum SystemFlags : uint
+{
+    DISALLOW_DELETE = 0x80000000,
+    CONFIG_ALLOW_RENAME = 0x40000000,
+    CONFIG_ALLOW_MOVE = 0x20000000,
+    CONFIG_ALLOW_LIMITED_MOVE = 0x10000000,
+    DOMAIN_DISALLOW_RENAME = 0x8000000,
+    DOMAIN_DISALLOW_MOVE = 0x4000000,
+    DISALLOW_MOVE_ON_DELETE = 0x2000000,
+    ATTR_IS_RDN = 0x20,
+    SCHEMA_BASE_OBJECT = 0x10,
+    ATTR_IS_OPERATIONAL = 0x8,
+    ATTR_IS_CONSTRUCTED = 0x4,
+    PARTIAL_SET_MEMBER = 0x2,
+    NOT_REPLICATED = 0x1
+}
+'@
+}
+
+$codeBlock=[PSCustomObject][Ordered]@{
+    SupportedAttributes=@('systemFlags')
+    OnLoad = $null
+    OnSave = $null
+}
+$codeBlock.OnLoad = { 
+    param(
+    [object[]]$Values
+    )
+    Process
+    {
+        foreach($Value in $Values)
+        {
+            [SystemFlags].GetEnumValues().ForEach({if(($Value -band $_) -eq $_) {"$_"}})
+        }
+    }
+}
+$codeBlock.OnSave = { 
+    param(
+    [object[]]$Values
+    )
+    
+    Process
+    {
+        $retVal = 0
+        $Values.ForEach({ [SystemFlags]$val=$_; $retVal+=$val})
+        $retVal
+ 
+    }
+}
+$codeBlock
+