4.1.27.2 Server Behavior of the IDL_DRSVerifyNames Method

Informative summary of behavior: The server resolves each of a sequence of object names and returns its DSName and the values of zero or more of its attributes. The type of the input object name is indicated by the dwFlags field in the request. The IDL_DRSVerifyNames method verifies the names of both deleted and normal objects.

 ULONG
 IDL_DRSVerifyNames(
     [in, ref] DRS_HANDLE hDrs,
     [in] DWORD dwInVersion,
     [in, ref, switch_is(dwInVersion)]
         DRS_MSG_VERIFYREQ *pmsgIn,
     [out, ref] DWORD *pdwOutVersion,
     [out, ref, switch_is(*pdwOutVersion)]
         DRS_MSG_VERIFYREPLY *pmsgOut);
  
 msgIn: DRS_MSG_VERIFYREQ_V1
 msgOut:  DRS_MSG_VERIFYREPLY_V1
 nc, d: DSName
 o: sequence of DSName
 i, j, k: int
 domainName, username: unicodestring
 done: boolean
 attribute: ATTRTYP
 FilterPAS: PARTIAL_ATTR_VECTOR_V1_EXT
 GCPas: PARTIAL_ATTR_VECTOR_V1_EXT
 referredDomain: unicodestring
  
 ValidateDRSInput(hDrs, 8)
  
 pdwOutVersion^ := 1
 pmsgOut^.V1.error := 0
 pmsgOut^.V1.cNames := 0
 pmsgOut^.V1.rpEntInf := null
 pmsgOut^.V1.PrefixTable.PrefixCount := 0
 pmsgOut^.V1.PrefixTable.pPrefixEntry := null
  
  
 /* Perform input validation and access check */
 if dwInVersion ≠ 0x1 then
   return ERROR_DS_DRA_INVALID_PARAMETER
 endif
 msgIn := pmsgIn^.V1
 if  msgIn.dwFlags ≠ DRS_VERIFY_DSNAMES and 
     msgIn.dwFlags ≠ DRS_VERIFY_SAM_ACCOUNT_NAMES and
     msgIn.dwFlags ≠ DRS_VERIFY_SIDS and
     msgIn.dwFlags ≠ DRS_VERIFY_FPOS then
   return ERROR_DS_DRA_INVALID_PARAMETER
 endif
 if msgIn.cNames > 0 and msgIn.rpNames = null then
   return ERROR_DS_DRA_INVALID_PARAMETER
 endif
 if (msgIn.dwFlags = DRS_VERIFY_SIDS or 
     msgIn.dwFlags = DRS_VERIFY_SAM_ACCOUNT_NAMES or
     msgIn.dwFlags = DRS_VERIFY_FPOS) and
     not IsGC() then
   return ERROR_DS_GC_REQUIRED
 endif
 if msgIn.dwFlags = DRS_VERIFY_DSNAMES and not IsGC() then
   for i := 0 to msgIn.cNames-1
     if DefaultNC() ≠ GetObjectNC(msgIn.rpNames[i]^) then
       return ERROR_DS_GC_REQUIRED
     endif
   endfor
 endif
  
 /* Compute output */
 msgOut.PrefixTable := dc.prefixTable
 for i := 0 to msgIn.cNames - 1
   d := msgIn.rpNames[i]
   o := null
   done := false
  
   if msgIn.dwFlags = DRS_VERIFY_SAM_ACCOUNT_NAMES then
     domainName := DomainNameFromNT4AccountName(d.dn)
     username := UserNameFromNT4AccountName(d.dn)
  
     if domainName ≠ null and username ≠ null and 
         IsDomainNameInTrustedForest(domainName, referredDomain) then
       /* Provide a hint as to which forest this name could be coming
        * from. Note that 0xFFFF0009 is a hardcoded attribute ID
        * recognized by clients of this method. This attribute ID does
        * not correspond to any attribute defined in the schema. */
       msgOut.rpEntInf[i].pName := null
       msgOut.rpEntInf[i].AttrBlock.AttrCount := 1
       msgOut.rpEntInt[i].AttrBlock.pAttr[0].AttrTyp := 0xFFFF0009
       msgOut.rpEntInf[i].AttrBlock.pAttr[0].AttrVal.valCount := 1
       msgOut.rpEntInf[i].AttrBlock.pAttr[0].AttrVal.pAVal[0].valLen 
       := Length in characters of domainName, excluding any
          terminating null
       msgOut.rpEntInf[i].AttrBlock.pAttr[0].AttrVal.pAVal[0].pAVal :=
           referredDomain
       done := true
     endif
   endif
  
   if not done
     /* locate object or objects in question */
     if msgIn.dwFlags = DRS_VERIFY_DSNAMES then
       if ObjExists(d) then
         o := {d}
       endif 
     else if msgIn.dwFlags = DRS_VERIFY_SIDS then
       o := select all v from all-ts-included 
           where v!objectSid = d.sid and
            foreignSecurityPrincipal not in v!objectClass 
     else if msgIn.dwFlags = DRS_VERIFY_SAM_ACCOUNT_NAMES then
       if domainName ≠ null and username ≠ null then
         nc := select one v from all
             where v!nETBIOSName = domainName and GetObjectNC(v)= v 
         /* The following query returns both normal objects
            and tombstones */
         o := select all v from subtree-ts-included nc where
             v!sAMAccountName = username 
       else
         o := select all v from all-ts-included
             where v!userPrincipalName =
             d.dn 
       endif
     else if msgIn.dwFlags = DRS_VERIFY_FPOS then
       o := select all v from all-ts-included 
             where v!objectSid = d.sid
               and foreignSecurityPrincipal in v!objectClass
     endif
  
     /* Compute returned info and get requested attributes */
     if o.length = 1 and AccessCheckCAR(GetObjectNC(o[0]), DS-Replication-Get-Changes) then
       msgOut.rpEntInf[i].pName = o[0]!distinguishedName
       if MasterReplicaExists(GetObjectNC(o[0])) then
         msgOut.rpEntInf[i].ulFlags := ENTINF_FROM_MASTER
       else
         msgOut.rpEntEnf[i].ulFlags := 0
       endif
       msgOut.rpEntInf[i].AttrBlock.AttrCount :=
           msgIn.RequiredAttrs.AttrCount
  
       FilterPas := FilteredPAS()
       GCPas := GCPAS()
  
       for j := 0 to msgIn.RequiredAttrs.AttrCount - 1
  
         if AmILHServer() then
           if (not (msgIn.RequiredAttrs.pAttr[j].AttrType in FilterPas
                    &&
                    msgIn.RequiredAttrs.pAttr[j].AttrType in GCPas))
             then
               /* skip requested attributes not part of both FilterPAS 
               and GCPas */
               msgOut.rpEntInf[i] := null
               continue;
           endif
         else
           /* pre-LH server */
           if (not (msgIn.RequiredAttrs.pAttr[j].AttrType in GCPas))
             then
               /* skip requested attributes not part of GCPas */
               msgOut.rpEntInf[i] := null
               continue;
           endif
         endif
  
         attribute := LocalAttidFromRemoteAttid(
                       msgIn.PrefixTable,
                       msgIn.RequiredAttrs.pAttr[j].attrTyp)
         msgOut.rpEntInf[i].AttrBlock.pAttr[j].attrTyp := attribute
         k := 0
         foreach val in GetAttrVals(o, attribute, false)
           msgOut.rpEntInf[i].AttrBlock.pAttr[j].AttrVal.pAVal :=
               ADR(ATTRVALFromValue(val,
                                    Syntax(attribute),
                                    dc.prefixTable))
           msgOut.rpEntInf[i].AttrBlock.pAttr[j].AttrVal.valCount :=
               k + 1
         endfor
       endfor
     else
       msgOut.rpEntInf[i] := null
     endif
   endif
 endfor /* i := */
  
 pmsgOut^.V1 := msgOut
 return 0