681 lines
20 KiB
C++
681 lines
20 KiB
C++
|
#include "cstore.hxx"
|
||
|
|
||
|
|
||
|
// set property routines do not do any allocations.
|
||
|
// get properties have 2 different sets of routines
|
||
|
// 1. in which there is no allocation taking place
|
||
|
// and the buffers are freed when the ds data structures
|
||
|
// are freed.
|
||
|
// 2. Allocation takes place and these should be used for
|
||
|
// data that needs to be returned back to the clients.
|
||
|
|
||
|
|
||
|
void FreeAttr(ADS_ATTR_INFO attr)
|
||
|
{
|
||
|
CoTaskMemFree(attr.pADsValues);
|
||
|
}
|
||
|
|
||
|
// Note: None of these APIs copies anything into their own buffers.
|
||
|
// It allocates a buffer for adsvalues though.
|
||
|
|
||
|
// packing a property's value into a attribute structure
|
||
|
// for sending in with a create/modify.
|
||
|
|
||
|
void PackStrArrToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty,
|
||
|
WCHAR **pszAttr, DWORD num)
|
||
|
{
|
||
|
DWORD i;
|
||
|
|
||
|
attr->pszAttrName = szProperty;
|
||
|
attr->dwNumValues = num;
|
||
|
|
||
|
if (num)
|
||
|
attr->dwControlCode = ADS_ATTR_UPDATE;
|
||
|
else
|
||
|
attr->dwControlCode = ADS_ATTR_CLEAR;
|
||
|
|
||
|
attr->dwADsType = ADSTYPE_DN_STRING;
|
||
|
attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
|
||
|
|
||
|
if (!(attr->pADsValues))
|
||
|
return; // BUGBUG:: return the hresult.
|
||
|
|
||
|
for (i = 0; i < num; i++) {
|
||
|
attr->pADsValues[i].dwType = ADSTYPE_DN_STRING;
|
||
|
attr->pADsValues[i].DNString = pszAttr[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PackDWArrToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, DWORD *pAttr, DWORD num)
|
||
|
{
|
||
|
DWORD i;
|
||
|
|
||
|
attr->pszAttrName = szProperty;
|
||
|
attr->dwNumValues = num;
|
||
|
|
||
|
if (num)
|
||
|
attr->dwControlCode = ADS_ATTR_UPDATE;
|
||
|
else
|
||
|
attr->dwControlCode = ADS_ATTR_CLEAR;
|
||
|
|
||
|
|
||
|
attr->dwADsType = ADSTYPE_INTEGER;
|
||
|
attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
|
||
|
if (!(attr->pADsValues))
|
||
|
return; // BUGBUG:: return the hresult.
|
||
|
|
||
|
for (i = 0; i < num; i++) {
|
||
|
attr->pADsValues[i].dwType = ADSTYPE_INTEGER;
|
||
|
attr->pADsValues[i].Integer = pAttr[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PackGUIDArrToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, GUID *pAttr, DWORD num)
|
||
|
{
|
||
|
DWORD i;
|
||
|
|
||
|
attr->pszAttrName = szProperty;
|
||
|
attr->dwNumValues = num;
|
||
|
|
||
|
if (num)
|
||
|
attr->dwControlCode = ADS_ATTR_UPDATE;
|
||
|
else
|
||
|
attr->dwControlCode = ADS_ATTR_CLEAR;
|
||
|
|
||
|
attr->dwADsType = ADSTYPE_OCTET_STRING;
|
||
|
attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
|
||
|
if (!(attr->pADsValues))
|
||
|
return; // BUGBUG:: return the hresult.
|
||
|
|
||
|
for (i = 0; i < num; i++) {
|
||
|
attr->pADsValues[i].dwType = ADSTYPE_OCTET_STRING;
|
||
|
attr->pADsValues[i].OctetString.dwLength = sizeof(GUID);
|
||
|
attr->pADsValues[i].OctetString.lpValue = (unsigned char *)(pAttr+i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PackBinToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, BYTE *pAttr, DWORD sz)
|
||
|
{
|
||
|
attr->pszAttrName = szProperty;
|
||
|
attr->dwNumValues = 1;
|
||
|
|
||
|
attr->dwControlCode = ADS_ATTR_UPDATE;
|
||
|
|
||
|
attr->dwADsType = ADSTYPE_OCTET_STRING;
|
||
|
attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE));
|
||
|
if (!(attr->pADsValues))
|
||
|
return; // BUGBUG:: return the hresult.
|
||
|
|
||
|
attr->pADsValues[0].dwType = ADSTYPE_OCTET_STRING;
|
||
|
attr->pADsValues[0].OctetString.dwLength = sz;
|
||
|
attr->pADsValues[0].OctetString.lpValue = pAttr;
|
||
|
}
|
||
|
|
||
|
void PackStrToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, WCHAR *szAttr)
|
||
|
{
|
||
|
if (szAttr)
|
||
|
PackStrArrToAttr(attr, szProperty, &szAttr, 1);
|
||
|
else
|
||
|
PackStrArrToAttr(attr, szProperty, &szAttr, 0);
|
||
|
}
|
||
|
|
||
|
void PackDWToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, DWORD Attr)
|
||
|
{
|
||
|
PackDWArrToAttr(attr, szProperty, &Attr, 1);
|
||
|
}
|
||
|
|
||
|
// passing in a pointer to GUID which is passed down into the LDAP structure.
|
||
|
|
||
|
void PackGUIDToAttr(ADS_ATTR_INFO *attr, WCHAR *szProperty, GUID *pAttr)
|
||
|
{
|
||
|
PackGUIDArrToAttr(attr, szProperty, pAttr, 1);
|
||
|
}
|
||
|
|
||
|
// returns the attribute corresp. to a given property.
|
||
|
DWORD GetPropertyFromAttr(ADS_ATTR_INFO *pattr, DWORD cNum, WCHAR *szProperty)
|
||
|
{
|
||
|
DWORD i;
|
||
|
for (i = 0; i < cNum; i++)
|
||
|
if (_wcsicmp(pattr[i].pszAttrName, szProperty) == 0)
|
||
|
break;
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT GetCategoryLocaleDesc(LPOLESTR *pdesc, ULONG cdesc, LCID *plcid,
|
||
|
LPOLESTR szDescription)
|
||
|
{
|
||
|
LCID plgid;
|
||
|
LPOLESTR ptr;
|
||
|
|
||
|
szDescription[0] = L'\0';
|
||
|
if (!cdesc)
|
||
|
return E_FAIL; // CAT_E_NODESCRIPTION;
|
||
|
|
||
|
// Try locale passed in
|
||
|
if (FindDescription(pdesc, cdesc, plcid, szDescription, 0))
|
||
|
return S_OK;
|
||
|
|
||
|
// Get default sublang local
|
||
|
plgid = PRIMARYLANGID((WORD)*plcid);
|
||
|
*plcid = MAKELCID(MAKELANGID(plgid, SUBLANG_DEFAULT), SORT_DEFAULT);
|
||
|
if (FindDescription(pdesc, cdesc, plcid, szDescription, 0))
|
||
|
return S_OK;
|
||
|
|
||
|
// Get matching lang id
|
||
|
if (FindDescription(pdesc, cdesc, plcid, szDescription, 1))
|
||
|
return S_OK;
|
||
|
|
||
|
// Get User Default
|
||
|
*plcid = GetUserDefaultLCID();
|
||
|
if (FindDescription(pdesc, cdesc, plcid, szDescription, 0))
|
||
|
return S_OK;
|
||
|
|
||
|
// Get System Default
|
||
|
*plcid = GetUserDefaultLCID();
|
||
|
if (FindDescription(pdesc, cdesc, plcid, szDescription, 0))
|
||
|
return S_OK;
|
||
|
|
||
|
// Get the first one
|
||
|
*plcid = wcstoul(pdesc[0], &ptr, 16);
|
||
|
if (szDescription)
|
||
|
{
|
||
|
if ((ptr) && (wcslen(ptr) >= (CAT_DESC_DELIM_LEN+2)))
|
||
|
wcscpy(szDescription, (ptr+CAT_DESC_DELIM_LEN+2));
|
||
|
else
|
||
|
szDescription = L'\0';
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------
|
||
|
// Returns the description corresp. to a LCID
|
||
|
// desc: list of descs+lcid
|
||
|
// cdesc: number of elements.
|
||
|
// plcid: the lcid in/out
|
||
|
// szDescription:description returned.
|
||
|
// GetPrimary: Match only the primary.
|
||
|
//---------------------------------------
|
||
|
|
||
|
ULONG FindDescription(LPOLESTR *desc, ULONG cdesc, LCID *plcid, LPOLESTR szDescription, BOOL GetPrimary)
|
||
|
{
|
||
|
ULONG i;
|
||
|
LCID newlcid;
|
||
|
LPOLESTR ptr;
|
||
|
for (i = 0; i < cdesc; i++)
|
||
|
{
|
||
|
newlcid = wcstoul(desc[i], &ptr, 16); // to be changed
|
||
|
// error to be checked.
|
||
|
if ((newlcid == *plcid) || ((GetPrimary) &&
|
||
|
(PRIMARYLANGID((WORD)*plcid) == PRIMARYLANGID(LANGIDFROMLCID(newlcid)))))
|
||
|
{
|
||
|
if (szDescription)
|
||
|
{
|
||
|
if ((ptr) && (wcslen(ptr) >= (CAT_DESC_DELIM_LEN+2)))
|
||
|
wcscpy(szDescription, (ptr+CAT_DESC_DELIM_LEN+2));
|
||
|
else
|
||
|
szDescription = L'\0';
|
||
|
}
|
||
|
if (GetPrimary)
|
||
|
*plcid = newlcid;
|
||
|
return i+1;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
DWORD NumDigits10(DWORD Value)
|
||
|
{
|
||
|
DWORD ret = 0;
|
||
|
|
||
|
for (ret = 0; Value != 0; ret++)
|
||
|
Value = Value/10;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
void ReportEventCS(HRESULT ErrorCode, HRESULT ExtendedErrorCode, LPOLESTR szContainerName)
|
||
|
{
|
||
|
|
||
|
WCHAR szErrCode[16];
|
||
|
LPCTSTR Msg[2];
|
||
|
HANDLE hEventLogHandle;
|
||
|
|
||
|
Msg[0] = szContainerName;
|
||
|
Msg[1] = szErrCode;
|
||
|
|
||
|
wsprintf(szErrCode, L"0x%x", ExtendedErrorCode);
|
||
|
|
||
|
|
||
|
hEventLogHandle = RegisterEventSource(NULL, CLASSSTORE_EVENT_SOURCE);
|
||
|
|
||
|
if (!hEventLogHandle)
|
||
|
{
|
||
|
#if DBG
|
||
|
// Don't want to call call CSDBGPrint
|
||
|
WCHAR Msg[_MAX_PATH];
|
||
|
wsprintf(Msg, L"CSTORE: ReportEventCS: Couldn't open event log. Error returned 0x%x\n", GetLastError());
|
||
|
OutputDebugString(Msg);
|
||
|
#endif // DBG
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
switch (ErrorCode) {
|
||
|
case CS_E_INVALID_VERSION:
|
||
|
ReportEvent(hEventLogHandle,
|
||
|
EVENTLOG_ERROR_TYPE,
|
||
|
0,
|
||
|
EVENT_CS_INVALID_VERSION,
|
||
|
NULL,
|
||
|
2,
|
||
|
0,
|
||
|
Msg,
|
||
|
NULL
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case CS_E_NETWORK_ERROR:
|
||
|
ReportEvent(hEventLogHandle,
|
||
|
EVENTLOG_ERROR_TYPE,
|
||
|
0,
|
||
|
EVENT_CS_NETWORK_ERROR,
|
||
|
NULL,
|
||
|
2,
|
||
|
0,
|
||
|
Msg,
|
||
|
NULL
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case CS_E_INVALID_PATH:
|
||
|
ReportEvent(hEventLogHandle,
|
||
|
EVENTLOG_ERROR_TYPE,
|
||
|
0,
|
||
|
EVENT_CS_INVALID_PATH,
|
||
|
NULL,
|
||
|
2,
|
||
|
0,
|
||
|
Msg,
|
||
|
NULL
|
||
|
);
|
||
|
break;
|
||
|
case CS_E_SCHEMA_MISMATCH:
|
||
|
ReportEvent(hEventLogHandle,
|
||
|
EVENTLOG_ERROR_TYPE,
|
||
|
0,
|
||
|
EVENT_CS_SCHEMA_MISMATCH,
|
||
|
NULL,
|
||
|
2,
|
||
|
0,
|
||
|
Msg,
|
||
|
NULL
|
||
|
);
|
||
|
break;
|
||
|
case CS_E_INTERNAL_ERROR:
|
||
|
ReportEvent(hEventLogHandle,
|
||
|
EVENTLOG_ERROR_TYPE,
|
||
|
0,
|
||
|
EVENT_CS_INTERNAL_ERROR,
|
||
|
NULL,
|
||
|
2,
|
||
|
0,
|
||
|
Msg,
|
||
|
NULL
|
||
|
);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
BOOL bDeregistered;
|
||
|
|
||
|
bDeregistered = DeregisterEventSource(hEventLogHandle);
|
||
|
|
||
|
if (!bDeregistered)
|
||
|
{
|
||
|
#if DBG
|
||
|
// Don't want to call call CSDBGPrint
|
||
|
WCHAR Msg[_MAX_PATH];
|
||
|
wsprintf(Msg, L"CSTORE: ReportEventCS: Couldn't Deregister event log. Error returned 0x%x\n", GetLastError());
|
||
|
OutputDebugString(Msg);
|
||
|
#endif // DBG
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// remapping Error Codes returned by LDAP to reasonable class store errors.
|
||
|
//
|
||
|
HRESULT RemapErrorCode(HRESULT ErrorCode, LPOLESTR m_szContainerName)
|
||
|
{
|
||
|
HRESULT RetCode;
|
||
|
|
||
|
if (SUCCEEDED(ErrorCode))
|
||
|
return S_OK;
|
||
|
|
||
|
switch (ErrorCode)
|
||
|
{
|
||
|
//
|
||
|
// All kinds of failures due to ObjectNotFound
|
||
|
// due to non-existence of object OR
|
||
|
// non-existent container OR
|
||
|
// invalid path specification
|
||
|
// Other than Access Denails
|
||
|
//
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_NO_RESULTS_RETURNED): // understand what causes this
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_NAME_ERROR_NOT_FOUND): // -do-
|
||
|
|
||
|
RetCode = CS_E_OBJECT_NOTFOUND; // which object - specific error
|
||
|
break;
|
||
|
|
||
|
case HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS):
|
||
|
case HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS):
|
||
|
case E_ADS_OBJECT_EXISTS:
|
||
|
RetCode = CS_E_OBJECT_ALREADY_EXISTS;
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// The following errors should not be expected normally.
|
||
|
// Class Store schema mismatched should be handled correctly.
|
||
|
// Errors below may ONLY occur for corrupted data OR out-of-band changes
|
||
|
// to a Class Store content.
|
||
|
|
||
|
case E_ADS_CANT_CONVERT_DATATYPE:
|
||
|
case E_ADS_SCHEMA_VIOLATION:
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_NO_ATTRIBUTE_OR_VALUE):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_CONSTRAINT_VIOLATION):
|
||
|
RetCode = CS_E_SCHEMA_MISMATCH;
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// Any kinds of Access or Auth Denial
|
||
|
// return ACCESS_DENIED
|
||
|
//
|
||
|
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_AUTH_METHOD_NOT_SUPPORTED):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_STRONG_AUTH_REQUIRED):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_CONFIDENTIALITY_REQUIRED):
|
||
|
case HRESULT_FROM_WIN32(ERROR_INVALID_PASSWORD):
|
||
|
case HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_AUTH_UNKNOWN):
|
||
|
|
||
|
RetCode = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
|
||
|
break;
|
||
|
|
||
|
case E_ADS_BAD_PATHNAME:
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_INVALID_ATTRIBUTE_SYNTAX): // this is wrong
|
||
|
RetCode = CS_E_INVALID_PATH;
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// Out of Memory
|
||
|
//
|
||
|
|
||
|
case HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY):
|
||
|
case HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY):
|
||
|
|
||
|
RetCode = E_OUTOFMEMORY;
|
||
|
break;
|
||
|
|
||
|
//
|
||
|
// Any DNS, DS or Network failures
|
||
|
//
|
||
|
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_NAME_ERROR_RESOLVING):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_NAME_ERROR_NOT_UNIQUE):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_NAME_ERROR_NO_MAPPING):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_NAME_ERROR_DOMAIN_ONLY):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_TIMELIMIT_EXCEEDED):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_BUSY):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_UNAVAILABLE):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_UNWILLING_TO_PERFORM):
|
||
|
case HRESULT_FROM_WIN32(ERROR_TIMEOUT):
|
||
|
case HRESULT_FROM_WIN32(ERROR_CONNECTION_REFUSED):
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN):
|
||
|
case HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN):
|
||
|
RetCode = CS_E_NETWORK_ERROR;
|
||
|
break;
|
||
|
|
||
|
case HRESULT_FROM_WIN32(ERROR_DS_ADMIN_LIMIT_EXCEEDED):
|
||
|
RetCode = CS_E_ADMIN_LIMIT_EXCEEDED;
|
||
|
break;
|
||
|
|
||
|
case CS_E_OBJECT_NOTFOUND:
|
||
|
case CS_E_OBJECT_ALREADY_EXISTS:
|
||
|
case CS_E_INVALID_VERSION:
|
||
|
case CS_E_PACKAGE_NOTFOUND:
|
||
|
RetCode = ErrorCode;
|
||
|
break;
|
||
|
|
||
|
case E_INVALIDARG:
|
||
|
case ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS:
|
||
|
RetCode = E_INVALIDARG;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
RetCode = CS_E_INTERNAL_ERROR;
|
||
|
}
|
||
|
|
||
|
CSDBGPrint((L"Error Code 0x%x remapped to 0x%x\n", ErrorCode, RetCode));
|
||
|
|
||
|
if ((RetCode == CS_E_INVALID_PATH) ||
|
||
|
(RetCode == CS_E_NETWORK_ERROR) ||
|
||
|
(RetCode == CS_E_INVALID_VERSION) ||
|
||
|
(RetCode == CS_E_SCHEMA_MISMATCH) ||
|
||
|
(RetCode == CS_E_INTERNAL_ERROR))
|
||
|
ReportEventCS(RetCode, ErrorCode, m_szContainerName);
|
||
|
|
||
|
return RetCode;
|
||
|
}
|
||
|
|
||
|
// These functions are used to delete a single value from a
|
||
|
// multivalued property or append to a multivalued property
|
||
|
|
||
|
void PackStrArrToAttrEx(ADS_ATTR_INFO *attr, WCHAR *szProperty, WCHAR **pszAttr, DWORD num,
|
||
|
BOOL APPEND)
|
||
|
{
|
||
|
DWORD i;
|
||
|
|
||
|
attr->pszAttrName = szProperty;
|
||
|
attr->dwNumValues = num;
|
||
|
|
||
|
if (APPEND)
|
||
|
attr->dwControlCode = ADS_ATTR_APPEND;
|
||
|
else
|
||
|
attr->dwControlCode = ADS_ATTR_DELETE;
|
||
|
|
||
|
attr->dwADsType = ADSTYPE_DN_STRING;
|
||
|
attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
|
||
|
if (!(attr->pADsValues))
|
||
|
return; // BUGBUG:: return the hresult.
|
||
|
|
||
|
for (i = 0; i < num; i++) {
|
||
|
attr->pADsValues[i].dwType = ADSTYPE_DN_STRING;
|
||
|
attr->pADsValues[i].DNString = pszAttr[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PackDWArrToAttrEx(ADS_ATTR_INFO *attr, WCHAR *szProperty, DWORD *pAttr, DWORD num,
|
||
|
BOOL APPEND)
|
||
|
{
|
||
|
DWORD i;
|
||
|
|
||
|
attr->pszAttrName = szProperty;
|
||
|
attr->dwNumValues = num;
|
||
|
|
||
|
if (APPEND)
|
||
|
attr->dwControlCode = ADS_ATTR_APPEND;
|
||
|
else
|
||
|
attr->dwControlCode = ADS_ATTR_DELETE;
|
||
|
|
||
|
attr->dwADsType = ADSTYPE_INTEGER;
|
||
|
attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
|
||
|
if (!(attr->pADsValues))
|
||
|
return; // BUGBUG:: return the hresult.
|
||
|
|
||
|
for (i = 0; i < num; i++) {
|
||
|
attr->pADsValues[i].dwType = ADSTYPE_INTEGER;
|
||
|
attr->pADsValues[i].Integer = pAttr[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void PackGUIDArrToAttrEx(ADS_ATTR_INFO *attr, WCHAR *szProperty, GUID *pAttr, DWORD num,
|
||
|
BOOL APPEND)
|
||
|
{
|
||
|
DWORD i;
|
||
|
|
||
|
attr->pszAttrName = szProperty;
|
||
|
attr->dwNumValues = num;
|
||
|
|
||
|
if (APPEND)
|
||
|
attr->dwControlCode = ADS_ATTR_APPEND;
|
||
|
else
|
||
|
attr->dwControlCode = ADS_ATTR_DELETE;
|
||
|
|
||
|
attr->dwADsType = ADSTYPE_OCTET_STRING;
|
||
|
attr->pADsValues = (ADSVALUE *)CoTaskMemAlloc(sizeof(ADSVALUE)*num);
|
||
|
if (!(attr->pADsValues))
|
||
|
return; // BUGBUG:: return the hresult.
|
||
|
|
||
|
for (i = 0; i < num; i++) {
|
||
|
attr->pADsValues[i].dwType = ADSTYPE_OCTET_STRING;
|
||
|
attr->pADsValues[i].OctetString.dwLength = sizeof(GUID);
|
||
|
attr->pADsValues[i].OctetString.lpValue = (unsigned char *)(pAttr+i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void LogMessage(WCHAR *wszDebugBuffer)
|
||
|
{
|
||
|
HANDLE hFile = NULL;
|
||
|
|
||
|
hFile = CreateFile(LOGFILE,
|
||
|
GENERIC_WRITE,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL);
|
||
|
|
||
|
if ( hFile != INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
if ( SetFilePointer (hFile, 0, NULL, FILE_END) != 0xFFFFFFFF )
|
||
|
{
|
||
|
char * pszString;
|
||
|
DWORD Size;
|
||
|
int Status;
|
||
|
|
||
|
Size = lstrlen(wszDebugBuffer) + 1;
|
||
|
pszString = (char *) CoTaskMemAlloc( Size );
|
||
|
|
||
|
if ( pszString )
|
||
|
{
|
||
|
Status = WideCharToMultiByte(
|
||
|
CP_ACP,
|
||
|
0,
|
||
|
wszDebugBuffer,
|
||
|
-1,
|
||
|
pszString,
|
||
|
Size,
|
||
|
NULL,
|
||
|
NULL );
|
||
|
|
||
|
if ( Status )
|
||
|
{
|
||
|
WriteFile(
|
||
|
hFile,
|
||
|
(LPCVOID) pszString,
|
||
|
lstrlenA(pszString) * sizeof(char),
|
||
|
&Size,
|
||
|
NULL );
|
||
|
|
||
|
}
|
||
|
}
|
||
|
CoTaskMemFree(pszString);
|
||
|
}
|
||
|
|
||
|
CloseHandle (hFile);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CSDbgPrint(WCHAR *Format, ...)
|
||
|
{
|
||
|
WCHAR wszDebugTitle[50], wszMsg[500];
|
||
|
SYSTEMTIME systime;
|
||
|
WCHAR wszDebugBuffer[500];
|
||
|
DWORD dwErrCode = 0;
|
||
|
va_list VAList;
|
||
|
LPCTSTR Msg[1];
|
||
|
|
||
|
if ((gDebugLog) || (gDebugOut))
|
||
|
{
|
||
|
dwErrCode = GetLastError();
|
||
|
|
||
|
va_start(VAList, Format);
|
||
|
GetLocalTime( &systime );
|
||
|
wsprintf( wszDebugTitle, L"CSTORE (%x) %02d:%02d:%02d:%03d ",
|
||
|
GetCurrentProcessId(),
|
||
|
systime.wHour, systime.wMinute, systime.wSecond,
|
||
|
systime.wMilliseconds);
|
||
|
|
||
|
wvsprintf(wszMsg, Format, VAList);
|
||
|
wsprintf(wszDebugBuffer, L"%s:: %s\n", wszDebugTitle, wszMsg);
|
||
|
if (gDebugOut)
|
||
|
OutputDebugString(wszDebugBuffer);
|
||
|
|
||
|
if (gDebugLog)
|
||
|
LogMessage(wszDebugBuffer);
|
||
|
|
||
|
if (gDebugEventLog)
|
||
|
{
|
||
|
HANDLE hEventLogHandle;
|
||
|
|
||
|
// we don't need time etc. for event log.
|
||
|
// it should be added
|
||
|
|
||
|
hEventLogHandle = RegisterEventSource(NULL, CLASSSTORE_EVENT_SOURCE);
|
||
|
|
||
|
if (!hEventLogHandle)
|
||
|
{
|
||
|
#if DBG
|
||
|
// Don't want to call call CSDBGPrint
|
||
|
WCHAR Msg[_MAX_PATH];
|
||
|
wsprintf(Msg, L"CSTORE: CSDbgPrint: Couldn't open event log. Error returned 0x%x\n", GetLastError());
|
||
|
OutputDebugString(Msg);
|
||
|
#endif // DBG
|
||
|
}
|
||
|
|
||
|
if (hEventLogHandle)
|
||
|
{
|
||
|
Msg[0] = wszMsg;
|
||
|
ReportEvent(hEventLogHandle,
|
||
|
EVENTLOG_INFORMATION_TYPE,
|
||
|
0,
|
||
|
EVENT_CS_CLASSSTORE_DEBUGMSG,
|
||
|
NULL,
|
||
|
1,
|
||
|
0,
|
||
|
Msg,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
BOOL bDeregistered;
|
||
|
|
||
|
bDeregistered = DeregisterEventSource(hEventLogHandle);
|
||
|
|
||
|
if (!bDeregistered)
|
||
|
{
|
||
|
#if DBG
|
||
|
// Don't want to call call CSDBGPrint
|
||
|
WCHAR Msg[_MAX_PATH];
|
||
|
wsprintf(Msg, L"CSTORE: CSDbgPrint: Couldn't Deregister event log. Error returned 0x%x\n", GetLastError());
|
||
|
OutputDebugString(Msg);
|
||
|
#endif // DBG
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
SetLastError(dwErrCode);
|
||
|
}
|
||
|
}
|
||
|
|