#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); } }