WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

DllCall Information

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

IntControl 32 and Pointers to Structures

 Keywords: IntControl 32 Byte Long Num2Char DsGetDcName Binary Buffer Structure _DOMAIN_CONTROLLER_INFOA Pointer

Update:

A more complete dsGetDcName code sample has been posted here: http://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WIL~Extenders/ADSI/Samples~from~Users+DsGetDcName.txt


Question:

Trying to execute the API call DsGetDcName and it is working but I am having trouble with the return info and the binary buffer. Everything I can find seems to say I am doing this somewhat correctly, except that the result is gibberish. It would be great if someone could tell me what I am missing here. The 'pause' title has the return value for the function call itself, and if I use a non-existent domain, or a 'flat' name I get the proper returns (1212 or 1355). But if I use a domain I am trying to get a DC for, I get no error, but can't make out the returned binary...

#DefineFunction fGetDC(sDomain) ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms675983(v=vs.85).aspx

   ;Flags to passed to DsGetDcName
   DS_FORCE_REDISCOVERY            =xHex(00000001)
   DS_DIRECTORY_SERVICE_REQUIRED   =xHex(00000010)
   DS_DIRECTORY_SERVICE_PREFERRED  =xHex(00000020)
   DS_GC_SERVER_REQUIRED           =xHex(00000040)
   DS_PDC_REQUIRED                 =xHex(00000080)
   DS_BACKGROUND_ONLY              =xHex(00000100)
   DS_IP_REQUIRED                  =xHex(00000200)
   DS_KDC_REQUIRED                 =xHex(00000400)
   DS_TIMESERV_REQUIRED            =xHex(00000800)
   DS_WRITABLE_REQUIRED            =xHex(00001000)
   DS_GOOD_TIMESERV_PREFERRED      =xHex(00002000)
   DS_AVOID_SELF                   =xHex(00004000)
   DS_ONLY_LDAP_NEEDED             =xHex(00008000)
   DS_IS_FLAT_NAME                 =xHex(00010000)
   DS_IS_DNS_NAME                  =xHex(00020000)
   DS_TRY_NEXTCLOSEST_SITE         =xHex(00040000)
   DS_DIRECTORY_SERVICE_6_REQ      =xHex(00080000) ;ORIGINAL NAME "DS_DIRECTORY_SERVICE_6_REQUIRED" renamed since WB does not support vars longer than 30 chars
   DS_WEB_SERVICE_REQUIRED         =xHex(00100000)
   DS_DIRECTORY_SERVICE_8_REQ      =xHex(00200000) ;ORIGINAL NAME "DS_DIRECTORY_SERVICE_8_REQUIRED" renamed since WB does not support vars longer than 30 chars
   DS_RETURN_DNS_NAME              =xHex(40000000)
   DS_RETURN_FLAT_NAME             =xHex(80000000)

   ;// Structure returned from DsGetDcName
   ;
   ;typedef struct _DOMAIN_CONTROLLER_INFOA { ; total size = 48bytes
   ;    LPSTR DomainControllerName;  as lpStr, width: 4, offset: 0
   ;    LPSTR DomainControllerAddress;  as lpStr, width: 4, offset: 4
   ;    ULONG DomainControllerAddressType; as long, width: 4, offset: 8
   ;    GUID DomainGuid;  as int,  width: 16, offset: 12
   ;    LPSTR DomainName;  as lpStr, width: 4, offset: 28
   ;    LPSTR DnsForestName;  as lpStr, width: 4, offset: 32
   ;    ULONG Flags;  as long, width: 4, offset: 36
   ;    LPSTR DcSiteName;  as lpStr, width: 4, offset: 40
   ;    LPSTR ClientSiteName;  as lpStr, width: 4, offset: 44
   ;} DOMAIN_CONTROLLER_INFOA, *PDOMAIN_CONTROLLER_INFOA;

   ;dllcall return values
   ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
   ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms681383(v=vs.85).aspx
   ERROR_SUCCESS                   =xHex(0)     ;0
   ERROR_INVALID_DOMAINNAME        =xHex("4BC") ;1212
   ERROR_INVALID_FLAGS             =xHex("3EC") ;1004
   ERROR_NOT_ENOUGH_MEMORY         =xHex(8)     ;8
   ERROR_NO_SUCH_DOMAIN            =xHex("54B") ;1355

   cbSize=48 ;callback structure size calculated above
   _DOMAIN_CONTROLLER_INFOA=BinaryAlloc(cbSize)
   BinaryEodSet(_DOMAIN_CONTROLLER_INFOA, cbSize)
   dll_NetAPI32=DllLoad(DirWindows(1):"Netapi32.dll")
   ret_dsGetDCName=DllCall(dll_NetAPI32, word:"DsGetDcNameA", lpNull, lpstr:sDomain, lpNull, lpNull, long:DS_IS_DNS_NAME, lpBinary:_DOMAIN_CONTROLLER_INFOA)
   sDC=BinaryPeekStr(_DOMAIN_CONTROLLER_INFOA, 0, 4)
   DllFree(dll_NetAPI32)
   BinaryFree(_DOMAIN_CONTROLLER_INFOA)
   Pause("Function Return: ":ret_dsGetDCName, "Domain Controller: ":sDC)
   Return(ret_dsGetDCName)
#EndFunction

AddExtender("wilx44i.dll")
fGetDC(AskLine("Get DC Function", "Enter full domain name:", "", 0))
Exit

Answer:

DsGetDcName's final parameter is a pointer to a PDOMAIN_CONTROLLER_INFO value that receives a pointer to a DOMAIN_CONTROLLER_INFO structure that contains data about the domain controller selected. This structure is allocated by DsGetDcName. The caller must free the structure using the NetApiBufferFree function when it is no longer required.

You will need to use IntControl 32 to get the structure's first element string pointer. Here is the revied code:

#DefineFunction fGetDC(sDomain) ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms675983(v=vs.85).aspx

   ;Flags to passed to DsGetDcName
   DS_FORCE_REDISCOVERY            =xHex(00000001)
   DS_DIRECTORY_SERVICE_REQUIRED   =xHex(00000010)
   DS_DIRECTORY_SERVICE_PREFERRED  =xHex(00000020)
   DS_GC_SERVER_REQUIRED           =xHex(00000040)
   DS_PDC_REQUIRED                 =xHex(00000080)
   DS_BACKGROUND_ONLY              =xHex(00000100)
   DS_IP_REQUIRED                  =xHex(00000200)
   DS_KDC_REQUIRED                 =xHex(00000400)
   DS_TIMESERV_REQUIRED            =xHex(00000800)
   DS_WRITABLE_REQUIRED            =xHex(00001000)
   DS_GOOD_TIMESERV_PREFERRED      =xHex(00002000)
   DS_AVOID_SELF                   =xHex(00004000)
   DS_ONLY_LDAP_NEEDED             =xHex(00008000)
   DS_IS_FLAT_NAME                 =xHex(00010000)
   DS_IS_DNS_NAME                  =xHex(00020000)
   DS_TRY_NEXTCLOSEST_SITE         =xHex(00040000)
   DS_DIRECTORY_SERVICE_6_REQ      =xHex(00080000) ;ORIGINAL NAME "DS_DIRECTORY_SERVICE_6_REQUIRED" renamed since WB does not support vars longer than 30 chars
   DS_WEB_SERVICE_REQUIRED         =xHex(00100000)
   DS_DIRECTORY_SERVICE_8_REQ      =xHex(00200000) ;ORIGINAL NAME "DS_DIRECTORY_SERVICE_8_REQUIRED" renamed since WB does not support vars longer than 30 chars
   DS_RETURN_DNS_NAME              =xHex(40000000)
   DS_RETURN_FLAT_NAME             =xHex(80000000)

   ;// Structure returned from DsGetDcName
   ;
   ;typedef struct _DOMAIN_CONTROLLER_INFOA { ; total size = 48bytes
   ;    LPSTR DomainControllerName;  as lpStr, width: 4, offset: 0
   ;    LPSTR DomainControllerAddress;  as lpStr, width: 4, offset: 4
   ;    ULONG DomainControllerAddressType; as long, width: 4, offset: 8
   ;    GUID DomainGuid;  as int,  width: 16, offset: 12
   ;    LPSTR DomainName;  as lpStr, width: 4, offset: 28
   ;    LPSTR DnsForestName;  as lpStr, width: 4, offset: 32
   ;    ULONG Flags;  as long, width: 4, offset: 36
   ;    LPSTR DcSiteName;  as lpStr, width: 4, offset: 40
   ;    LPSTR ClientSiteName;  as lpStr, width: 4, offset: 44
   ;} DOMAIN_CONTROLLER_INFOA, *PDOMAIN_CONTROLLER_INFOA;

    ;typedef struct _DOMAIN_CONTROLLER_INFOA { ; total size = 1660bytes
   ;    LPSTR DomainControllerName;  as lpStr, width: 256, offset: 0
   ;    LPSTR DomainControllerAddress;  as lpStr, width: 256, offset: 255
   ;    ULONG DomainControllerAddressType; as long, width: 4, offset: 512
   ;    GUID DomainGuid;  as int,  width: 16, offset: 516
   ;    LPSTR DomainName;  as lpStr, width: 256, offset: 632
   ;    LPSTR DnsForestName;  as lpStr, width: 256, offset: 888
   ;    ULONG Flags;  as long, width: 4, offset: 1144
   ;    LPSTR DcSiteName;  as lpStr, width: 256, offset: 1148
   ;    LPSTR ClientSiteName;  as lpStr, width: 256, offset: 1404
   ;} DOMAIN_CONTROLLER_INFOA, *PDOMAIN_CONTROLLER_INFOA;

   ;dllcall return values
   ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
   ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms681383(v=vs.85).aspx
   ERROR_SUCCESS                   =xHex(0)     ;0
   ERROR_INVALID_DOMAINNAME        =xHex("4BC") ;1212
   ERROR_INVALID_FLAGS             =xHex("3EC") ;1004
   ERROR_NOT_ENOUGH_MEMORY         =xHex(8)     ;8
   ERROR_NO_SUCH_DOMAIN            =xHex("54B") ;1355


   hppDC = BinaryAlloc(4)
   dll_NetAPI32=DllLoad(DirWindows(1):"Netapi32.dll")
   ret_dsGetDCName=DllCall(dll_NetAPI32, long:"DsGetDcNameA", lpNull, lpstr:sDomain, lpNull, lpNull, long:DS_RETURN_DNS_NAME, lpbinary:hppDC) ;;DS_IS_FLAT_NAME  DS_RETURN_DNS_NAME

   sDc  = ""
   ppDC = BinaryPeek4( hppDC, 0)
   pStr = IntControl(32,ppDC, "LONG", 0,0)  ; Structure's first element string pointer here.
   cValue = IntControl(32, pStr , "BYTE", 0,0)
   While cValue
      sDc = sDc:Num2Char(cValue)
      pStr = pStr + 1
      cValue = IntControl(32,pStr, "BYTE", 0,0)
   EndWhile

   DllCall(dll_NetAPI32, long:"NetApiBufferFree", long:ppDC)

   BinaryFree(hppDC)
   DllFree(dll_NetAPI32)

   Pause("Function Return: ":ret_dsGetDCName, "Domain Controller: ":sDC)

   Return(ret_dsGetDCName)

#EndFunction


AddExtender("wilx44i.dll")
fGetDC(AskLine("Get DC Function", "Enter full domain name:", "", 0))
Exit

Article ID:   W17792
Filename:   IntControl 32 and Structures.txt
File Created: 2014:07:18:09:50:36
Last Updated: 2014:07:18:09:50:36