UTIL.CXX

//--------------------------------------------------------------------------- 
//
// Microsoft Active Directory 1.1 Sample Code
//
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: util.cxx
//
// Contents: Ansi to Unicode conversions and misc helper functions
//
//----------------------------------------------------------------------------//------------------------------------------------------------------------------

#include "main.hxx"

void
PrintUsage(
void
)
{

printf("\nUsage: adsqry /b <baseObject> /f <search_filter> /a <attrlist> [/p <preference=value>] ");
printf(" [/u <UserName> <Password>] /d <dialect> \n");
printf("\n where:\n" );
printf(" baseObject = ADsPath of the base of the search\n");
printf(" search_filter = search filter string in LDAP format\n" );
printf(" attrlist = list of the attributes to display\n" );
printf(" dialect is one of \"ldap\", \"sql\", or \"default\"\n");
printf(" preference could be one of:\n");
printf(" Asynchronous, AttrTypesOnly, DerefAliases, SizeLimit, TimeLimit,\n");
printf(" TimeOut, PageSize, SearchScope, SecureAuth and EncryptPassword\n");
printf(" value is yes/no for a Boolean and the respective integer for integers\n");
printf(" scope is one of \"Base\", \"OneLevel\", or \"Subtree\"\n");

printf("\nFor Example: adsqry /b \"LDAP://server1/O=Internet/DC=COM/");
printf("DC=MyCompany/DC=MyDivision\" /f \"(objectClass=Group)\" /a \"ADsPath, name, description\" ");
printf(" /u \"CN=FooUser,CN=Users,DC=MyDivision,DC=MyCompany,DC=COM,O=INTERNET\" \"Password\" \n");

printf("\nFor Example: adsqry /b \"LDAP://O=Internet/DC=COM/");
printf("DC=MyCompany/DC=MyDivision\" /f \"objectClass='Group'\" /a \"ADsPath, name, description\" ");
printf(" /d sql /u \"CN=FooUser,CN=Users,DC=MyDivision,DC=MyCompany,DC=COM,O=INTERNET\" \"Password\" \n");

}


//
// Form the bindings array to specify the way the provider has to put the
// data in consumer's buffers; Create the Accessor from the bindings
//
HRESULT
CreateAccessorHelper(
IRowset *pIRowset,
ULONG nAttrs,
DBCOLUMNINFO *prgColInfo,
HACCESSOR *phAccessor,
DBBINDSTATUS *pBindStatus
)
{

DBBINDING *prgBindings = NULL;
HRESULT hr;
ULONG i;
IAccessor *pIAccessor = NULL;

if(!phAccessor || !pBindStatus)
return(E_INVALIDARG);

prgBindings = (DBBINDING *) LocalAlloc(
LPTR,
sizeof(DBBINDING) * nAttrs
);
BAIL_ON_NULL(prgBindings);

//
// Set up rest of the attributes
//
for (i=0; i < nAttrs; i++) {
prgBindings[i].iOrdinal = i+1;
prgBindings[i].wType= prgColInfo[i+1].wType;
if (prgBindings[i].wType == DBTYPE_DATE || prgBindings[i].wType == DBTYPE_I8)
prgBindings[i].obValue = sizeof(Data)*i + offsetof(Data, obValue2);
else
prgBindings[i].obValue = sizeof(Data)*i + offsetof(Data, obValue);
prgBindings[i].obLength= sizeof(Data)*i + offsetof(Data, obLength);
prgBindings[i].obStatus= sizeof(Data)*i + offsetof(Data, status);
prgBindings[i].dwPart= DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS;

if(prgBindings[i].wType & DBTYPE_BYREF)
prgBindings[i].dwMemOwner= DBMEMOWNER_PROVIDEROWNED;
else
prgBindings[i].dwMemOwner= DBMEMOWNER_CLIENTOWNED;

prgBindings[i].dwFlags= 0;
}


hr= pIRowset->QueryInterface(
IID_IAccessor,
(void**) &pIAccessor
);
BAIL_ON_FAILURE(hr);

//
// With the bindings create the accessor
//
hr = pIAccessor->CreateAccessor(
DBACCESSOR_ROWDATA,
nAttrs,
prgBindings,
0,
phAccessor,
pBindStatus
);

pIAccessor->Release();
LOCAL_FREE(prgBindings);

return(hr);

error:
LOCAL_FREE(prgBindings);

return(hr);

}

//
// Print the data depending on its type.
//

void
PrintData(
Data *prgData,
ULONG nAttrs,
DBCOLUMNINFO *prgColInfo
)
{

ULONG i, j;
HRESULT hr;

for (i=0; i < nAttrs; i++) {

if(prgData[i].status == DBSTATUS_S_OK) {

switch(prgColInfo[i+1].wType) {
case DBTYPE_I4:
wprintf(
L"%s = %d \n",
prgColInfo[i+1].pwszName,
(DWORD) prgData[i].obValue
);
break;

case DBTYPE_I8:
wprintf(
L"%s = %I64d \n",
prgColInfo[i+1].pwszName,
*((__int64 *) &prgData[i].obValue2)
);
break;

case DBTYPE_BOOL:
wprintf(
L"%s = %s \n",
prgColInfo[i+1].pwszName,
*((VARIANT_BOOL *) &(prgData[i].obValue)) == VARIANT_TRUE ?
L"TRUE" : L"FALSE"
);
break;

case DBTYPE_STR | DBTYPE_BYREF:
wprintf(
L"%s = ",
prgColInfo[i+1].pwszName
);
printf(
"%s \n",
(char *)prgData[i].obValue
);
break;

case DBTYPE_BYTES | DBTYPE_BYREF:
wprintf(
L"%s = ",
prgColInfo[i+1].pwszName
);
for (j=0; j<prgData[i].obLength; j++) {
printf(
"%x",
((BYTE *)prgData[i].obValue)[j]
);
}
printf("\n");
break;

case DBTYPE_WSTR | DBTYPE_BYREF:
wprintf(
L"%s = %s \n",
prgColInfo[i+1].pwszName,
(WCHAR *) prgData[i].obValue
);
break;

case DBTYPE_DATE:
wprintf(
L"%s = %e \n",
prgColInfo[i+1].pwszName,
prgData[i].obValue2
);
break;

case DBTYPE_VARIANT | DBTYPE_BYREF:
wprintf(
L"%s = ",
prgColInfo[i+1].pwszName
);

ULONG dwSLBound;
ULONG dwSUBound;
void HUGEP *pArray;
VARIANT *pVariant;

pArray = NULL;

pVariant = (VARIANT*) prgData[i].obValue;

if( !(pVariant->vt & VT_ARRAY))
BAIL_ON_FAILURE(hr = E_FAIL);

hr = SafeArrayGetLBound(V_ARRAY(pVariant),
1,
(long FAR *) &dwSLBound );
BAIL_ON_FAILURE(hr);

hr = SafeArrayGetUBound(V_ARRAY(pVariant),
1,
(long FAR *) &dwSUBound );
BAIL_ON_FAILURE(hr);

hr = SafeArrayAccessData( V_ARRAY(pVariant),
&pArray );
BAIL_ON_FAILURE(hr);

for (j=dwSLBound; j<=dwSUBound; j++) {
switch(pVariant->vt & ~VT_ARRAY) {
case VT_BSTR:
wprintf(
L"%s # ",
((BSTR *)pArray)[j]
);
break;
case VT_I4:
wprintf(
L"%d # ",
((DWORD *) pArray)[j]
);
break;
case VT_BOOL:
wprintf(
L"%s # ",
((VARIANT_BOOL *) pArray)[j] == VARIANT_TRUE ?
L"TRUE" : L"FALSE"
);
break;
case VT_I8:
wprintf(
L"%I64d # ",
((__int64 *) pArray)[j]
);
break;

default:
wprintf(
L"Unsupported # \n"
);
}
}
printf("\n");

SafeArrayUnaccessData( V_ARRAY(pVariant) );

break;

default:
wprintf(
L"Unsupported type for attribute %s\n",
prgColInfo[i+1].pwszName
);
break;
}
}

}

if(nAttrs != 0)
wprintf(L"\n");

return;

error:
wprintf(
L"Error in Printing data for %s\n",
prgColInfo[i+1].pwszName
);
return;

}


int
AnsiToUnicodeString(
LPSTR pAnsi,
LPWSTR pUnicode,
DWORD StringLength
)
{
int iReturn;

if( StringLength == NULL_TERMINATED )
StringLength = strlen( pAnsi );

iReturn = MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
pAnsi,
StringLength + 1,
pUnicode,
StringLength + 1 );

//
// Ensure NULL termination.
//
pUnicode[StringLength] = 0;

return iReturn;
}


int
UnicodeToAnsiString(
LPWSTR pUnicode,
LPSTR pAnsi,
DWORD StringLength
)
{
LPSTR pTempBuf = NULL;
INT rc = 0;

if( StringLength == NULL_TERMINATED ) {

//
// StringLength is just the
// number of characters in the string
//
StringLength = wcslen( pUnicode );
}

//
// WideCharToMultiByte doesn't NULL terminate if we're copying
// just part of the string, so terminate here.
//

pUnicode[StringLength] = 0;

//
// Include one for the NULL
//
StringLength++;

//
// Unfortunately, WideCharToMultiByte doesn't do conversion in place,
// so allocate a temporary buffer, which we can then copy:
//

if( pAnsi == (LPSTR)pUnicode )
{
#ifdef DBCS
pTempBuf = (LPSTR)LocalAlloc( LPTR, StringLength * 2 );
#else
pTempBuf = (LPSTR)LocalAlloc( LPTR, StringLength );
#endif
pAnsi = pTempBuf;
}

if( pAnsi )
{
rc = WideCharToMultiByte( CP_ACP,
0,
pUnicode,
StringLength,
pAnsi,
#ifdef DBCS
StringLength*2,
#else
StringLength,
#endif
NULL,
NULL );
}

/* If pTempBuf is non-null, we must copy the resulting string
* so that it looks as if we did it in place:
*/
if( pTempBuf && ( rc > 0 ) )
{
pAnsi = (LPSTR)pUnicode;
strcpy( pAnsi, pTempBuf );
LocalFree( pTempBuf );
}

return rc;
}


LPWSTR
AllocateUnicodeString(
LPSTR pAnsiString
)
{
LPWSTR pUnicodeString = NULL;

if (!pAnsiString)
return NULL;

pUnicodeString = (LPWSTR)LocalAlloc(
LPTR,
strlen(pAnsiString)*sizeof(WCHAR) +sizeof(WCHAR)
);

if (pUnicodeString) {

AnsiToUnicodeString(
pAnsiString,
pUnicodeString,
NULL_TERMINATED
);
}

return pUnicodeString;
}


void
FreeUnicodeString(
LPWSTR pUnicodeString
)
{
if (!pUnicodeString)
return;

LocalFree(pUnicodeString);

return;
}