313 lines
6 KiB
C++
313 lines
6 KiB
C++
//---------------------------------------------------------------------------
|
||
//
|
||
// Microsoft Active Directory 1.0 Sample Code
|
||
//
|
||
// Copyright (C) Microsoft Corporation, 1992 - 1995
|
||
//
|
||
// File: util.cxx
|
||
//
|
||
// Contents: Ansi to Unicode conversions and misc helper functions
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
|
||
#include "main.hxx"
|
||
|
||
//
|
||
// Local functions
|
||
//
|
||
|
||
|
||
int
|
||
AnsiToUnicodeString(
|
||
LPSTR pAnsi,
|
||
LPWSTR pUnicode,
|
||
DWORD StringLength
|
||
)
|
||
{
|
||
int iReturn;
|
||
|
||
if( StringLength == 0 )
|
||
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 == 0 ) {
|
||
|
||
//
|
||
// 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 )
|
||
{
|
||
pTempBuf = (LPSTR)LocalAlloc( LPTR, StringLength );
|
||
pAnsi = pTempBuf;
|
||
}
|
||
|
||
if( pAnsi )
|
||
{
|
||
rc = WideCharToMultiByte( CP_ACP,
|
||
0,
|
||
pUnicode,
|
||
StringLength,
|
||
pAnsi,
|
||
StringLength,
|
||
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,
|
||
0
|
||
);
|
||
}
|
||
|
||
return pUnicodeString;
|
||
}
|
||
|
||
|
||
void
|
||
FreeUnicodeString(
|
||
LPWSTR pUnicodeString
|
||
)
|
||
{
|
||
|
||
LocalFree(pUnicodeString);
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
//
|
||
// Misc helper functions for displaying data.
|
||
//
|
||
|
||
|
||
HRESULT
|
||
PrintVariant(
|
||
VARIANT varPropData
|
||
)
|
||
{
|
||
HRESULT hr;
|
||
BSTR bstrValue;
|
||
|
||
switch (varPropData.vt) {
|
||
case VT_I4:
|
||
printf("%d", varPropData.lVal);
|
||
break;
|
||
case VT_BSTR:
|
||
printf("%S", varPropData.bstrVal);
|
||
break;
|
||
|
||
case VT_BOOL:
|
||
printf("%d", V_BOOL(&varPropData));
|
||
break;
|
||
|
||
case (VT_ARRAY | VT_VARIANT):
|
||
PrintVariantArray(varPropData);
|
||
break;
|
||
|
||
case VT_DATE:
|
||
hr = VarBstrFromDate(
|
||
varPropData.date,
|
||
LOCALE_SYSTEM_DEFAULT,
|
||
LOCALE_NOUSEROVERRIDE,
|
||
&bstrValue
|
||
);
|
||
printf("%S", bstrValue);
|
||
break;
|
||
|
||
default:
|
||
printf("Data type is %d\n", varPropData.vt);
|
||
break;
|
||
|
||
}
|
||
printf("\n");
|
||
return(S_OK);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
PrintVariantArray(
|
||
VARIANT var
|
||
)
|
||
{
|
||
LONG dwSLBound = 0;
|
||
LONG dwSUBound = 0;
|
||
VARIANT v;
|
||
LONG i;
|
||
HRESULT hr = S_OK;
|
||
|
||
if(!((V_VT(&var) & VT_VARIANT) && V_ISARRAY(&var))) {
|
||
return(E_FAIL);
|
||
}
|
||
|
||
//
|
||
// Check that there is only one dimension in this array
|
||
//
|
||
|
||
if ((V_ARRAY(&var))->cDims != 1) {
|
||
hr = E_FAIL;
|
||
BAIL_ON_FAILURE(hr);
|
||
}
|
||
//
|
||
// Check that there is atleast one element in this array
|
||
//
|
||
|
||
if ((V_ARRAY(&var))->rgsabound[0].cElements == 0){
|
||
hr = E_FAIL;
|
||
BAIL_ON_FAILURE(hr);
|
||
}
|
||
|
||
//
|
||
// We know that this is a valid single dimension array
|
||
//
|
||
|
||
hr = SafeArrayGetLBound(V_ARRAY(&var),
|
||
1,
|
||
(long FAR *)&dwSLBound
|
||
);
|
||
BAIL_ON_FAILURE(hr);
|
||
|
||
hr = SafeArrayGetUBound(V_ARRAY(&var),
|
||
1,
|
||
(long FAR *)&dwSUBound
|
||
);
|
||
BAIL_ON_FAILURE(hr);
|
||
|
||
for (i = dwSLBound; i <= dwSUBound; i++) {
|
||
VariantInit(&v);
|
||
hr = SafeArrayGetElement(V_ARRAY(&var),
|
||
(long FAR *)&i,
|
||
&v
|
||
);
|
||
if (FAILED(hr)) {
|
||
continue;
|
||
}
|
||
if (i < dwSUBound) {
|
||
printf("%S, ", v.bstrVal);
|
||
} else {
|
||
printf("%S", v.bstrVal);
|
||
}
|
||
}
|
||
return(S_OK);
|
||
|
||
error:
|
||
return(hr);
|
||
}
|
||
|
||
|
||
HRESULT
|
||
PrintProperty(
|
||
BSTR bstrPropName,
|
||
HRESULT hRetVal,
|
||
VARIANT varPropData
|
||
)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
|
||
switch (hRetVal) {
|
||
|
||
case 0:
|
||
printf("%-32S: ", bstrPropName);
|
||
PrintVariant(varPropData);
|
||
break;
|
||
|
||
case E_ADS_CANT_CONVERT_DATATYPE:
|
||
printf("%-32S: ", bstrPropName);
|
||
printf("<Data could not be converted for display>\n");
|
||
break;
|
||
|
||
default:
|
||
printf("%-32S: ", bstrPropName);
|
||
printf("<Data not available>\n");
|
||
break;
|
||
|
||
}
|
||
return(hr);
|
||
}
|
||
|
||
void
|
||
PrintUsage(
|
||
void
|
||
)
|
||
{
|
||
printf("usage: adscmd [list|dump] <ADsPath>\n") ;
|
||
}
|
||
|
||
|