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.

281 lines
9.9 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. CSEOComModule *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. LPOLESTR pszAPPID = NULL; // The APPID as a string.
  32. if (!pparmeResult) {
  33. // The caller did not give us a place to return the result.
  34. return (E_POINTER);
  35. }
  36. *pparmeResult = NULL; // For the first time through the loop, the result is NULL.
  37. // We are going to loop through twice. The first time through, we haven't allocate the map yet, so
  38. // we will count all the strings, and add up their lenghts - this will give us the size of the buffer
  39. // we need to allocate for the map. Then the second time through the loop, we will store all the
  40. // strings in the map.
  41. while (1) {
  42. if (pclsid) {
  43. // If we were passed a CLSID, then we want to include that in the map.
  44. if (!*pparmeResult) {
  45. // If this is the first time through, then we need to convert the CLSID to a string.
  46. HRESULT hrRes;
  47. hrRes = StringFromCLSID(*pclsid,&pszCLSID);
  48. if (!SUCCEEDED(hrRes)) {
  49. // We failed to convert the CLSID to a string.
  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 and APPID 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. if (!*pparmeResult) {
  151. // If this is the first time through, see if an APPID is provided by the
  152. // module.
  153. const GUID *pappid = pmodule->GetAPPID();
  154. if (pappid) {
  155. // If there is an APPID, convert it to a string.
  156. HRESULT hrRes;
  157. hrRes = StringFromCLSID(*pappid,&pszAPPID);
  158. if (!SUCCEEDED(hrRes)) {
  159. // We failed to convert the APPID to a string.
  160. CoTaskMemFree(pszCLSID);
  161. return (hrRes);
  162. }
  163. }
  164. }
  165. if (pszAPPID) {
  166. // If the module provides an APPID, we need to add it to the map.
  167. if (*pparmeResult) {
  168. // If this isn't the first time through, then we already have the APPID as a string,
  169. // so we just need to put it in the map.
  170. (*pparmeResult)[dwCnt].szKey = L"APPID";
  171. (*pparmeResult)[dwCnt].szData = (LPCOLESTR) pbAdd;
  172. wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szData,pszAPPID);
  173. }
  174. // Whether or not this is the first time through, we increment some stuff based on the
  175. // size of the APPID string and the fact that we have a APPID in the map.
  176. pbAdd += (wcslen(pszAPPID)+1) * sizeof(OLECHAR);
  177. dwCnt++;
  178. if (*pparmeResult) {
  179. // If this is not the first time through, make sure we clean up after ourselves.
  180. CoTaskMemFree(pszAPPID);
  181. pszAPPID = NULL;
  182. }
  183. }
  184. }
  185. { // Now we need to go through the varargs. All of the varargs must be LPOLESTR (i.e. they
  186. // must be UNICODE), and they will consist of pairs - the key name followed by the data. If
  187. // either member of the pair is NULL, that signals the end of the varargs.
  188. va_list valArgs;
  189. // Set the va_list to the start of the varargs.
  190. va_start(valArgs,pszIndex);
  191. while (1) {
  192. LPCOLESTR pszKey;
  193. LPCOLESTR pszData;
  194. // Get the first of the pair - this is the key name.
  195. pszKey = va_arg(valArgs,LPCOLESTR);
  196. if (!pszKey) {
  197. break;
  198. }
  199. // Get the second of the pair - this is the data.
  200. pszData = va_arg(valArgs,LPCOLESTR);
  201. if (!pszData) {
  202. break;
  203. }
  204. if (*pparmeResult) {
  205. // If this isn't the first time through, then we need to store the key name to the
  206. // map.
  207. (*pparmeResult)[dwCnt].szKey = (LPCOLESTR) pbAdd;
  208. wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szKey,pszKey);
  209. }
  210. // Whether or not this is the first time through, we increment some stuff based on the
  211. // size of the string.
  212. pbAdd += (wcslen(pszKey)+1) * sizeof(OLECHAR);
  213. if (*pparmeResult) {
  214. // If this isn't the first time through, then we need to store the data to the map.
  215. (*pparmeResult)[dwCnt].szData = (LPCOLESTR) pbAdd;
  216. wcscpy((LPOLESTR) (*pparmeResult)[dwCnt].szData,pszData);
  217. }
  218. // Whether or not this is the first time through, we increment some stuff based on the
  219. // size of the string and the fact that we have a string in the map.
  220. pbAdd += (wcslen(pszData)+1) * sizeof(OLECHAR);
  221. dwCnt++;
  222. }
  223. // Reset the va_list, for the sake of cleanliness.
  224. va_end(valArgs);
  225. }
  226. if (*pparmeResult) {
  227. // If we have allocated the map, that means that we are finishing the second time through
  228. // the loop - so we are done!
  229. break;
  230. }
  231. if (!*pparmeResult) {
  232. // If we havemn't allocate the map, that means that we are finishing the first time through
  233. // the loop - so we need to allocate the map in preparation for the second time through.
  234. // First we calculate the number of bytes needed for the map - this is one ATL_REGMAP_ENTRY
  235. // for each entry, plus one _ATL_REGMAP_ENTRY which signals the end of the map, plus enough
  236. // space for all of the strings to follow.
  237. DWORD dwBytes = (dwCnt + 1) * sizeof(_ATL_REGMAP_ENTRY) + (DWORD)(pbAdd-(LPBYTE) NULL);
  238. *pparmeResult = (_ATL_REGMAP_ENTRY *) CoTaskMemAlloc(dwBytes);
  239. if (!*pparmeResult) {
  240. // The memory allocation failed.
  241. CoTaskMemFree(pszCLSID);
  242. CoTaskMemFree(pszTLID);
  243. CoTaskMemFree(pszAPPID);
  244. return (E_OUTOFMEMORY);
  245. }
  246. // The memory allocation was successful - fill the memory with zeroes in preparation for
  247. // loading with the values.
  248. memset(*pparmeResult,0,dwBytes);
  249. // Reset the counters to the "beginning" - so that on the second time through, they are used
  250. // to keep track of where each successive value gets stored in the memory block.
  251. pbAdd = ((LPBYTE) *pparmeResult) + (dwCnt + 1) * sizeof(_ATL_REGMAP_ENTRY);
  252. dwCnt = 0;
  253. }
  254. }
  255. return (S_OK);
  256. }