/*++ Copyright (c) 1996 Microsoft Corporation Module Name: StdAfx.cpp Abstract: This module contains the implementation for the base ATL methods. Author: Don Dumitru (dondu@microsoft.com) Revision History: dondu 12/04/96 created --*/ // stdafx.cpp : source file that includes just the standard includes // stdafx.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h" #ifdef _ATL_STATIC_REGISTRY #include #include #endif #include HRESULT AtlAllocRegMapEx(_ATL_REGMAP_ENTRY **pparmeResult, const CLSID *pclsid, CSEOComModule *pmodule, LPCOLESTR pszIndex, ...) { LPBYTE pbAdd = NULL; // Working pointer to the next available "scratch space" in the map. DWORD dwCnt = 0; // The count of entries in the map. LPOLESTR pszCLSID = NULL; // The CLSID as a string. LPOLESTR pszTLID = NULL; // The TLID as a string. LPOLESTR pszAPPID = NULL; // The APPID as a string. if (!pparmeResult) { // The caller did not give us a place to return the result. return (E_POINTER); } *pparmeResult = NULL; // For the first time through the loop, the result is NULL. // We are going to loop through twice. The first time through, we haven't allocate the map yet, so // we will count all the strings, and add up their lenghts - this will give us the size of the buffer // we need to allocate for the map. Then the second time through the loop, we will store all the // strings in the map. while (1) { if (pclsid) { // If we were passed a CLSID, then we want to include that in the map. if (!*pparmeResult) { // If this is the first time through, then we need to convert the CLSID to a string. HRESULT hrRes; hrRes = StringFromCLSID(*pclsid,&pszCLSID); if (!SUCCEEDED(hrRes)) { // We failed to convert the CLSID to a string. return (hrRes); } } else { // If this isn't the first time through, then we already have the CLSID as a string, so // we just need to put it in the map. (*pparmeResult)[dwCnt].szKey = L"CLSID"; (*pparmeResult)[dwCnt].szData = (LPCOLESTR) pbAdd; wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szData,pszCLSID); } // Whether or not this is the first time through, we increment some stuff based on the size // of the CLSID string and the fact that we have a CLSID in the map. pbAdd += (wcslen(pszCLSID)+1) * sizeof(OLECHAR); dwCnt++; if (*pparmeResult) { // If this is not the first time through, make sure we clean up after ourselves. CoTaskMemFree(pszCLSID); pszCLSID = NULL; } } if (pmodule) { // If we were passed a module, then we want to include the TLID and APPID in the map. if (!*pparmeResult) { // If this is the first time through, then we need to load the type library, get its // TLID, and convert it to a string. USES_CONVERSION; HRESULT hrRes; TCHAR szModule[MAX_PATH]; LPOLESTR pszModule; CComPtr pTypeLib; TLIBATTR *ptlaAttr; if (!GetModuleFileName(pmodule->GetTypeLibInstance(), szModule, sizeof(szModule)/sizeof(TCHAR))) { hrRes = HRESULT_FROM_WIN32(GetLastError()); if (SUCCEEDED(hrRes)) { // GetModuleFileName() failed, but GetLastError() didn't report an error - so // fake it. hrRes = E_OUTOFMEMORY; } CoTaskMemFree(pszCLSID); return (hrRes); } if (pszIndex) { // If we were passed an index, that means that the type library desired is not the // first type library in the resources - so append the index to the module name. lstrcat(szModule,OLE2T(pszIndex)); } pszModule = T2OLE(szModule); hrRes = LoadTypeLib(pszModule,&pTypeLib); if (!SUCCEEDED(hrRes)) { // If we couldn't load the type library from the module, let's try changing the // module name to a type library name (change the extension to .TLB) and try to load // *that*. LPTSTR pszExt = NULL; LPTSTR psz; for (psz=szModule;*psz;psz=CharNext(psz)) { if (*psz == _T('.')) { pszExt = psz; } } if (!pszExt) { pszExt = psz; } lstrcpy(pszExt,_T(".tlb")); pszModule = T2OLE(szModule); hrRes = LoadTypeLib(pszModule,&pTypeLib); } if (!SUCCEEDED(hrRes)) { // We failed to load the type library. CoTaskMemFree(pszCLSID); return (hrRes); } hrRes = pTypeLib->GetLibAttr(&ptlaAttr); if (!SUCCEEDED(hrRes)) { // We failed to get the type library attributes. CoTaskMemFree(pszCLSID); return (hrRes); } hrRes = StringFromCLSID(ptlaAttr->guid,&pszTLID); if (!SUCCEEDED(hrRes)) { // We failed to convert the TLID to a string. CoTaskMemFree(pszCLSID); return (hrRes); } } else { // If this isn't the first time through, then we already have the TLID as a string, so // we just need to put it in the map. (*pparmeResult)[dwCnt].szKey = L"LIBID"; (*pparmeResult)[dwCnt].szData = (LPCOLESTR) pbAdd; wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szData,pszTLID); } // Whether or not this is the first time through, we increment some stuff based on the size // of the TLID string and the fact that we have a TLID in the map. pbAdd += (wcslen(pszTLID)+1) * sizeof(OLECHAR); dwCnt++; if (*pparmeResult) { // If this is not the first time through, make sure we clean up after ourselves. CoTaskMemFree(pszTLID); pszTLID = NULL; } if (!*pparmeResult) { // If this is the first time through, see if an APPID is provided by the // module. const GUID *pappid = pmodule->GetAPPID(); if (pappid) { // If there is an APPID, convert it to a string. HRESULT hrRes; hrRes = StringFromCLSID(*pappid,&pszAPPID); if (!SUCCEEDED(hrRes)) { // We failed to convert the APPID to a string. CoTaskMemFree(pszCLSID); return (hrRes); } } } if (pszAPPID) { // If the module provides an APPID, we need to add it to the map. if (*pparmeResult) { // If this isn't the first time through, then we already have the APPID as a string, // so we just need to put it in the map. (*pparmeResult)[dwCnt].szKey = L"APPID"; (*pparmeResult)[dwCnt].szData = (LPCOLESTR) pbAdd; wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szData,pszAPPID); } // Whether or not this is the first time through, we increment some stuff based on the // size of the APPID string and the fact that we have a APPID in the map. pbAdd += (wcslen(pszAPPID)+1) * sizeof(OLECHAR); dwCnt++; if (*pparmeResult) { // If this is not the first time through, make sure we clean up after ourselves. CoTaskMemFree(pszAPPID); pszAPPID = NULL; } } } { // Now we need to go through the varargs. All of the varargs must be LPOLESTR (i.e. they // must be UNICODE), and they will consist of pairs - the key name followed by the data. If // either member of the pair is NULL, that signals the end of the varargs. va_list valArgs; // Set the va_list to the start of the varargs. va_start(valArgs,pszIndex); while (1) { LPCOLESTR pszKey; LPCOLESTR pszData; // Get the first of the pair - this is the key name. pszKey = va_arg(valArgs,LPCOLESTR); if (!pszKey) { break; } // Get the second of the pair - this is the data. pszData = va_arg(valArgs,LPCOLESTR); if (!pszData) { break; } if (*pparmeResult) { // If this isn't the first time through, then we need to store the key name to the // map. (*pparmeResult)[dwCnt].szKey = (LPCOLESTR) pbAdd; wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szKey,pszKey); } // Whether or not this is the first time through, we increment some stuff based on the // size of the string. pbAdd += (wcslen(pszKey)+1) * sizeof(OLECHAR); if (*pparmeResult) { // If this isn't the first time through, then we need to store the data to the map. (*pparmeResult)[dwCnt].szData = (LPCOLESTR) pbAdd; wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szData,pszData); } // Whether or not this is the first time through, we increment some stuff based on the // size of the string and the fact that we have a string in the map. pbAdd += (wcslen(pszData)+1) * sizeof(OLECHAR); dwCnt++; } // Reset the va_list, for the sake of cleanliness. va_end(valArgs); } if (*pparmeResult) { // If we have allocated the map, that means that we are finishing the second time through // the loop - so we are done! break; } if (!*pparmeResult) { // If we havemn't allocate the map, that means that we are finishing the first time through // the loop - so we need to allocate the map in preparation for the second time through. // First we calculate the number of bytes needed for the map - this is one ATL_REGMAP_ENTRY // for each entry, plus one _ATL_REGMAP_ENTRY which signals the end of the map, plus enough // space for all of the strings to follow. DWORD dwBytes = (dwCnt + 1) * sizeof(_ATL_REGMAP_ENTRY) + (DWORD)(pbAdd-(LPBYTE) NULL); *pparmeResult = (_ATL_REGMAP_ENTRY *) CoTaskMemAlloc(dwBytes); if (!*pparmeResult) { // The memory allocation failed. CoTaskMemFree(pszCLSID); CoTaskMemFree(pszTLID); CoTaskMemFree(pszAPPID); return (E_OUTOFMEMORY); } // The memory allocation was successful - fill the memory with zeroes in preparation for // loading with the values. memset(*pparmeResult,0,dwBytes); // Reset the counters to the "beginning" - so that on the second time through, they are used // to keep track of where each successive value gets stored in the memory block. pbAdd = ((LPBYTE) *pparmeResult) + (dwCnt + 1) * sizeof(_ATL_REGMAP_ENTRY); dwCnt = 0; } } return (S_OK); }