You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
281 lines
9.9 KiB
281 lines
9.9 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
StdAfx.cpp
|
|
|
|
Abstract:
|
|
|
|
This module contains the implementation for the base
|
|
ATL methods.
|
|
|
|
Author:
|
|
|
|
Don Dumitru ([email protected])
|
|
|
|
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 <statreg.h>
|
|
#include <statreg.cpp>
|
|
#endif
|
|
|
|
#include <atlimpl.cpp>
|
|
|
|
|
|
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<ITypeLib> 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);
|
|
}
|