Leaked source code of windows server 2003
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.

244 lines
8.6 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. StdAfx.cpp
  5. Abstract:
  6. This module contains the implementation for the base
  7. ATL methods.
  8. Author:
  9. Don Dumitru (dondu@microsoft.com)
  10. Revision History:
  11. dondu 12/04/96 created
  12. --*/
  13. // stdafx.cpp : source file that includes just the standard includes
  14. // stdafx.pch will be the pre-compiled header
  15. // stdafx.obj will contain the pre-compiled type information
  16. #include "stdafx.h"
  17. #ifdef _ATL_STATIC_REGISTRY
  18. #include <statreg.h>
  19. #include <statreg.cpp>
  20. #endif
  21. #include <atlimpl.cpp>
  22. HRESULT AtlAllocRegMapEx(_ATL_REGMAP_ENTRY **pparmeResult,
  23. const CLSID *pclsid,
  24. CComModule *pmodule,
  25. LPCOLESTR pszIndex,
  26. ...) {
  27. LPBYTE pbAdd = NULL; // Working pointer to the next available "scratch space" in the map.
  28. DWORD dwCnt = 0; // The count of entries in the map.
  29. LPOLESTR pszCLSID = NULL; // The CLSID as a string.
  30. LPOLESTR pszTLID = NULL; // The TLID as a string.
  31. if (!pparmeResult) {
  32. // The caller did not give us a place to return the result.
  33. return (E_POINTER);
  34. }
  35. *pparmeResult = NULL; // For the first time through the loop, the result is NULL.
  36. // We are going to loop through twice. The first time through, we haven't allocate the map yet, so
  37. // we will count all the strings, and add up their lenghts - this will give us the size of the buffer
  38. // we need to allocate for the map. Then the second time through the loop, we will store all the
  39. // strings in the map.
  40. while (1) {
  41. if (pclsid) {
  42. // If we were passed a CLSID, then we want to include that in the map.
  43. if (!*pparmeResult) {
  44. // If this is the first time through, then we need to convert the CLSID to a string.
  45. HRESULT hrRes;
  46. hrRes = StringFromCLSID(*pclsid,&pszCLSID);
  47. if (!SUCCEEDED(hrRes)) {
  48. // We failed to convert the CLSID to a string.
  49. CoTaskMemFree(*pparmeResult);
  50. return (hrRes);
  51. }
  52. } else {
  53. // If this isn't the first time through, then we already have the CLSID as a string, so
  54. // we just need to put it in the map.
  55. (*pparmeResult)[dwCnt].szKey = L"CLSID";
  56. (*pparmeResult)[dwCnt].szData = (LPCOLESTR) pbAdd;
  57. wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szData,pszCLSID);
  58. }
  59. // Whether or not this is the first time through, we increment some stuff based on the size
  60. // of the CLSID string and the fact that we have a CLSID in the map.
  61. pbAdd += (wcslen(pszCLSID)+1) * sizeof(OLECHAR);
  62. dwCnt++;
  63. if (*pparmeResult) {
  64. // If this is not the first time through, make sure we clean up after ourselves.
  65. CoTaskMemFree(pszCLSID);
  66. pszCLSID = NULL;
  67. }
  68. }
  69. if (pmodule) {
  70. // If we were passed a module, then we want to include the TLID in the map.
  71. if (!*pparmeResult) {
  72. // If this is the first time through, then we need to load the type library, get its
  73. // TLID, and convert it to a string.
  74. USES_CONVERSION;
  75. HRESULT hrRes;
  76. TCHAR szModule[MAX_PATH];
  77. LPOLESTR pszModule;
  78. CComPtr<ITypeLib> pTypeLib;
  79. TLIBATTR *ptlaAttr;
  80. if (!GetModuleFileName(pmodule->GetTypeLibInstance(),
  81. szModule,
  82. sizeof(szModule)/sizeof(TCHAR))) {
  83. hrRes = HRESULT_FROM_WIN32(GetLastError());
  84. if (SUCCEEDED(hrRes)) {
  85. // GetModuleFileName() failed, but GetLastError() didn't report an error - so
  86. // fake it.
  87. hrRes = E_OUTOFMEMORY;
  88. }
  89. CoTaskMemFree(pszCLSID);
  90. return (hrRes);
  91. }
  92. if (pszIndex) {
  93. // If we were passed an index, that means that the type library desired is not the
  94. // first type library in the resources - so append the index to the module name.
  95. lstrcat(szModule,OLE2T(pszIndex));
  96. }
  97. pszModule = T2OLE(szModule);
  98. hrRes = LoadTypeLib(pszModule,&pTypeLib);
  99. if (!SUCCEEDED(hrRes)) {
  100. // If we couldn't load the type library from the module, let's try changing the
  101. // module name to a type library name (change the extension to .TLB) and try to load
  102. // *that*.
  103. LPTSTR pszExt = NULL;
  104. LPTSTR psz;
  105. for (psz=szModule;*psz;psz=CharNext(psz)) {
  106. if (*psz == _T('.')) {
  107. pszExt = psz;
  108. }
  109. }
  110. if (!pszExt) {
  111. pszExt = psz;
  112. }
  113. lstrcpy(pszExt,_T(".tlb"));
  114. pszModule = T2OLE(szModule);
  115. hrRes = LoadTypeLib(pszModule,&pTypeLib);
  116. }
  117. if (!SUCCEEDED(hrRes)) {
  118. // We failed to load the type library.
  119. CoTaskMemFree(pszCLSID);
  120. return (hrRes);
  121. }
  122. hrRes = pTypeLib->GetLibAttr(&ptlaAttr);
  123. if (!SUCCEEDED(hrRes)) {
  124. // We failed to get the type library attributes.
  125. CoTaskMemFree(pszCLSID);
  126. return (hrRes);
  127. }
  128. hrRes = StringFromCLSID(ptlaAttr->guid,&pszTLID);
  129. if (!SUCCEEDED(hrRes)) {
  130. // We failed to convert the TLID to a string.
  131. CoTaskMemFree(pszCLSID);
  132. return (hrRes);
  133. }
  134. } else {
  135. // If this isn't the first time through, then we already have the TLID as a string, so
  136. // we just need to put it in the map.
  137. (*pparmeResult)[dwCnt].szKey = L"LIBID";
  138. (*pparmeResult)[dwCnt].szData = (LPCOLESTR) pbAdd;
  139. wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szData,pszTLID);
  140. }
  141. // Whether or not this is the first time through, we increment some stuff based on the size
  142. // of the TLID string and the fact that we have a TLID in the map.
  143. pbAdd += (wcslen(pszTLID)+1) * sizeof(OLECHAR);
  144. dwCnt++;
  145. if (*pparmeResult) {
  146. // If this is not the first time through, make sure we clean up after ourselves.
  147. CoTaskMemFree(pszTLID);
  148. pszTLID = NULL;
  149. }
  150. }
  151. { // Now we need to go through the varargs. All of the varargs must be LPOLESTR (i.e. they
  152. // must be UNICODE), and they will consist of pairs - the key name followed by the data. If
  153. // either member of the pair is NULL, that signals the end of the varargs.
  154. va_list valArgs;
  155. // Set the va_list to the start of the varargs.
  156. va_start(valArgs,pszIndex);
  157. while (1) {
  158. LPCOLESTR pszKey;
  159. LPCOLESTR pszData;
  160. // Get the first of the pair - this is the key name.
  161. pszKey = va_arg(valArgs,LPCOLESTR);
  162. if (!pszKey) {
  163. break;
  164. }
  165. // Get the second of the pair - this is the data.
  166. pszData = va_arg(valArgs,LPCOLESTR);
  167. if (!pszData) {
  168. break;
  169. }
  170. if (*pparmeResult) {
  171. // If this isn't the first time through, then we need to store the key name to the
  172. // map.
  173. (*pparmeResult)[dwCnt].szKey = (LPCOLESTR) pbAdd;
  174. wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szKey,pszKey);
  175. }
  176. // Whether or not this is the first time through, we increment some stuff based on the
  177. // size of the string.
  178. pbAdd += (wcslen(pszKey)+1) * sizeof(OLECHAR);
  179. if (*pparmeResult) {
  180. // If this isn't the first time through, then we need to store the data to the map.
  181. (*pparmeResult)[dwCnt].szData = (LPCOLESTR) pbAdd;
  182. wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szData,pszData);
  183. }
  184. // Whether or not this is the first time through, we increment some stuff based on the
  185. // size of the string and the fact that we have a string in the map.
  186. pbAdd += (wcslen(pszData)+1) * sizeof(OLECHAR);
  187. dwCnt++;
  188. }
  189. // Reset the va_list, for the sake of cleanliness.
  190. va_end(valArgs);
  191. }
  192. if (*pparmeResult) {
  193. // If we have allocated the map, that means that we are finishing the second time through
  194. // the loop - so we are done!
  195. break;
  196. }
  197. if (!*pparmeResult) {
  198. // If we havemn't allocate the map, that means that we are finishing the first time through
  199. // the loop - so we need to allocate the map in preparation for the second time through.
  200. // First we calculate the number of bytes needed for the map - this is one ATL_REGMAP_ENTRY
  201. // for each entry, plus one _ATL_REGMAP_ENTRY which signals the end of the map, plus enough
  202. // space for all of the strings to follow.
  203. DWORD dwBytes = (DWORD)((dwCnt + 1) * sizeof(_ATL_REGMAP_ENTRY) + (pbAdd-(LPBYTE) NULL));
  204. *pparmeResult = (_ATL_REGMAP_ENTRY *) CoTaskMemAlloc(dwBytes);
  205. if (!*pparmeResult) {
  206. // The memory allocation failed.
  207. CoTaskMemFree(pszCLSID);
  208. CoTaskMemFree(pszTLID);
  209. return (E_OUTOFMEMORY);
  210. }
  211. // The memory allocation was successful - fill the memory with zeroes in preparation for
  212. // loading with the values.
  213. memset(*pparmeResult,0,dwBytes);
  214. // Reset the counters to the "beginning" - so that on the second time through, they are used
  215. // to keep track of where each successive value gets stored in the memory block.
  216. pbAdd = ((LPBYTE) *pparmeResult) + (dwCnt + 1) * sizeof(_ATL_REGMAP_ENTRY);
  217. dwCnt = 0;
  218. }
  219. }
  220. return (S_OK);
  221. }