Source code of Windows XP (NT5)
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.

410 lines
13 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: olescm.cxx
  7. //
  8. // Contents: Functions shared between OLE32 and the SCM
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 10-03-95 kevinro Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <windows.h>
  18. #include <ole2sp.h>
  19. #include <ole2com.h>
  20. static const WCHAR wszOle32Dll[] = L"OLE32.DLL";
  21. #define OLE32_DLL wszOle32Dll
  22. #define OLE32_BYTE_LEN sizeof(OLE32_DLL)
  23. #define OLE32_CHAR_LEN (sizeof(OLE32_DLL) / sizeof(WCHAR) - 1)
  24. //
  25. // Threading Model Registry Constants
  26. //
  27. const WCHAR wszDllThreadModel[] = L"ThreadingModel";
  28. const WCHAR wszAptModel[] = L"Apartment";
  29. const WCHAR wszBothModel[] = L"Both";
  30. const WCHAR wszFreeModel[] = L"Free";
  31. const WCHAR wszNeutralModel[] = L"Neutral";
  32. // Thread model match table. The table's first index is the threading
  33. // model of the process and can be either APT_THREADED or
  34. // FREE_THREADED. The second index is any one of the types of threading
  35. // model's for DLLs.
  36. BOOL afThreadModelMatch[2][4] =
  37. {{TRUE, FALSE, TRUE, TRUE},
  38. {FALSE, TRUE, FALSE, TRUE}};
  39. //+---------------------------------------------------------------------------
  40. //
  41. // Function: CompareDllName
  42. //
  43. // Synopsis: Give a DLL path, this sees if the path is equal to a given
  44. // DLL name or the last component of the is the same as the
  45. // DLL name.
  46. //
  47. // Arguments: [pwszPath] -- DLL path
  48. // [pwszDllName] -- name of DLL to compare with
  49. //
  50. // Returns: TRUE - The input path is equal or its last component is equal
  51. // to the input Dll name.
  52. // FALSE - Not equal at all.
  53. //
  54. // History: 6-15-95 ricksa Created
  55. //
  56. // Notes: This is a helper function used by the routines that convert
  57. // ole2.dll to ole32.dll and to convert paths that end in ole32.dll
  58. // into ole32.dll.
  59. //
  60. //----------------------------------------------------------------------------
  61. BOOL
  62. wCompareDllName(LPCWSTR pwszPath, LPCWSTR pwszDllName, DWORD dwDllNameLen)
  63. {
  64. BOOL fResult = TRUE;
  65. if (lstrcmpiW(pwszDllName, pwszPath) != 0)
  66. {
  67. // Check if the last component is the same path
  68. DWORD dwPathLen = lstrlenW(pwszPath);
  69. if (dwPathLen > dwDllNameLen)
  70. {
  71. // Point to the last where the slash would be if the substitute
  72. // path is the last component
  73. LPCWSTR pwszLastComponent = pwszPath + dwPathLen - (dwDllNameLen + 1);
  74. // Is there a slash in that position
  75. if ((*pwszLastComponent == '\\') || (*pwszLastComponent == '/'))
  76. {
  77. // Point to where the last component should be
  78. pwszLastComponent++;
  79. // Does the last component match?
  80. if (lstrcmpiW(pwszLastComponent, pwszDllName) == 0)
  81. {
  82. goto CompareDllName_Exit;
  83. }
  84. }
  85. }
  86. fResult = FALSE;
  87. }
  88. CompareDllName_Exit:
  89. return fResult;
  90. }
  91. //+-------------------------------------------------------------------------
  92. //
  93. // Function: wThreadModelMatch
  94. //
  95. // Synopsis: Determines whether caller and DLL thread models match
  96. //
  97. // Arguments: [dwCallerThreadModel] - Caller thread model
  98. // [dwDllThreadModel] - DLL thread model
  99. //
  100. // Returns: TRUE - DLL can be loaded caller
  101. // FALSE - DLL cannot be loaded into caller.
  102. //
  103. // Algorithm: If the caller's thread model is apartment, then check
  104. // whether the DLL is one of apartment, single threaded or
  105. // both threaded. If it is, then return TRUE. Otherwise,
  106. // for free threading return TRUE if the DLL model is either
  107. // both or free threaded. If neither of the above is TRUE
  108. // then return FALSE.
  109. //
  110. // History: 10-Nov-94 Ricksa Created
  111. //
  112. //--------------------------------------------------------------------------
  113. BOOL wThreadModelMatch(
  114. DWORD dwCallerThreadModel,
  115. DWORD dwDllThreadModel,
  116. DWORD dwContext)
  117. {
  118. BOOL fResult = afThreadModelMatch[dwCallerThreadModel] [dwDllThreadModel];
  119. if (dwContext & CLSCTX_PS_DLL)
  120. {
  121. fResult = TRUE;
  122. }
  123. return fResult;
  124. }
  125. //+-------------------------------------------------------------------------
  126. //
  127. // Function: wQueryStripRegValue
  128. //
  129. // Synopsis: Get the DLL information for a 32 bit DLL and
  130. // strip off any leading and trailing "
  131. //
  132. // Arguments: [hkey] - class handle
  133. // [pwszSubKey] - key to open
  134. // [pwszValue] - where to return data
  135. // [pcbValue] - length of above buffer in bytes
  136. //
  137. // Returns: ERROR_SUCCESS - read DLL path information
  138. // Other - registry entries could not be found
  139. //
  140. // Algorithm: Read the value requested.
  141. // If first character is not ", exit
  142. // Otherwise, copy data after quote to beginning of buffer.
  143. //
  144. //
  145. // History: 05-Jan-94 BillMo Created
  146. // 26-Sep-95 BruceMa Support environment variable expansion
  147. // for shell viewers
  148. //
  149. //--------------------------------------------------------------------------
  150. LONG
  151. wQueryStripRegValue(HKEY hKey, // handle of key to query
  152. LPCWSTR pwszSubKey, // address of name of subkey to query
  153. LPWSTR pwszValue, // address of buffer for returned string
  154. PLONG pcbValue) // address of buffer for size of returned string
  155. {
  156. HKEY hSubKey;
  157. DWORD dwType;
  158. LONG lErr ;
  159. Win4Assert(pwszValue != NULL);
  160. Win4Assert(pcbValue != NULL);
  161. //
  162. // Open the subkey if there is a string
  163. //
  164. if (pwszSubKey != NULL)
  165. {
  166. lErr = RegOpenKeyExW(hKey, pwszSubKey, NULL, KEY_READ, &hSubKey);
  167. }
  168. else
  169. {
  170. hSubKey = hKey;
  171. lErr = ERROR_SUCCESS;
  172. }
  173. // Read the value into the user's buffer
  174. if (lErr == ERROR_SUCCESS)
  175. {
  176. lErr = RegQueryValueExW(hSubKey, NULL , NULL, &dwType,
  177. (BYTE *) pwszValue, (ULONG *) pcbValue);
  178. if (lErr == ERROR_SUCCESS)
  179. {
  180. WCHAR *pwszScan = pwszValue; // used to scan along string
  181. WCHAR *pwszDest = pwszValue; // used as destination when copying
  182. // if the name is quoted then ...
  183. if (*pwszScan == '\"')
  184. {
  185. pwszScan++;
  186. // copy all non-quote characters down to base of buffer
  187. // until end of quoted string
  188. while (*pwszScan != '\0' && *pwszScan != '\"')
  189. {
  190. *pwszDest++ = *pwszScan++;
  191. }
  192. // terminate string and get length in bytes including nul
  193. *pwszDest++ = '\0';
  194. *pcbValue = (int)(pwszDest - pwszValue) * sizeof(WCHAR);
  195. }
  196. // find first non-white space character
  197. pwszScan = pwszValue;
  198. while (_istspace(*pwszScan))
  199. pwszScan++;
  200. // if there are no non-white space characters this will be true
  201. if (*pwszScan == L'\0')
  202. {
  203. lErr = ERROR_FILE_NOT_FOUND;
  204. *pcbValue = 0;
  205. }
  206. // Chicago does not support ExpandEnvironmentStrings
  207. #ifndef _CHICAGO_
  208. // If the value type is REG_EXPAND_SZ then do environment variable
  209. // expansion
  210. if (dwType == REG_EXPAND_SZ)
  211. {
  212. // Expand any embedded environemnt variable expressions
  213. WCHAR wszTemp[MAX_PATH];
  214. lstrcpyW(wszTemp, pwszValue);
  215. *pcbValue = ExpandEnvironmentStrings(wszTemp, pwszValue,MAX_PATH);
  216. }
  217. #endif // !_CHICAGO_
  218. }
  219. //
  220. // Only close the sub key if we actually opened it.
  221. //
  222. if (hSubKey != hKey)
  223. {
  224. RegCloseKey(hSubKey);
  225. }
  226. }
  227. return lErr;
  228. }
  229. //+-------------------------------------------------------------------------
  230. //
  231. // Function: GetDllInfo
  232. //
  233. // Synopsis: Get the DLL information for a 32 bit DLL
  234. //
  235. // Arguments: [hClsRegEntry] - class handle
  236. // [pwszKey] - key to open
  237. // [pwszDllName] - where to return DLL path
  238. // [pclDllName] - length of above buffer
  239. // [pulDllThreadType] - where to return DLL threading information
  240. //
  241. // Returns: ERROR_SUCCESS - read DLL path information
  242. // Other - registry entries could not be found
  243. //
  244. // Algorithm: Open the DLL key. Then read the DLL path name. Finally read
  245. // the threading model information if it is specified.
  246. //
  247. // History: 09-Nov-94 Ricksa Created
  248. //
  249. //--------------------------------------------------------------------------
  250. LONG wGetDllInfo(
  251. HKEY hClsRegEntry,
  252. LPCWSTR pwszKey,
  253. LPWSTR pwszDllName,
  254. LONG* pclDllName,
  255. ULONG* pulDllThreadType)
  256. {
  257. HKEY hDllEntry = NULL;
  258. //
  259. // Attempt to open the specified registry key.
  260. //
  261. LONG lerr = RegOpenKeyW(hClsRegEntry, pwszKey, &hDllEntry);
  262. if (ERROR_SUCCESS == lerr)
  263. {
  264. //
  265. // Try to read the DLL name.
  266. //
  267. lerr = wQueryStripRegValue(hDllEntry, NULL, pwszDllName, pclDllName);
  268. if (ERROR_SUCCESS == lerr)
  269. {
  270. //
  271. // A DLL name is registered. If the DLL is OLE32.DLL, then we
  272. // know all about and don't have to dig more info from the
  273. // the registry. Otherwise, we do need to keep digging.
  274. //
  275. if (wCompareDllName(pwszDllName, OLE32_DLL, OLE32_CHAR_LEN))
  276. {
  277. memcpy(pwszDllName, OLE32_DLL, OLE32_BYTE_LEN);
  278. *pclDllName = OLE32_CHAR_LEN;
  279. *pulDllThreadType = BOTH_THREADED;
  280. }
  281. else
  282. {
  283. //
  284. // Assume there is no registry entry.
  285. //
  286. *pulDllThreadType = SINGLE_THREADED;
  287. //
  288. // Buffer to hold entry for the registry data.
  289. //
  290. WCHAR wszModelBuf[MAX_PATH];
  291. DWORD cdwModelBuf = sizeof(wszModelBuf);
  292. DWORD dwRegEntType;
  293. //
  294. // Read the DLL threading model from the registry.
  295. //
  296. lerr = RegQueryValueExW(hDllEntry,
  297. wszDllThreadModel,
  298. NULL,
  299. &dwRegEntType,
  300. (LPBYTE) &wszModelBuf[0],
  301. &cdwModelBuf);
  302. //
  303. // If there is a thread model descriptor, set the thread
  304. // type accordingly.
  305. //
  306. if (ERROR_SUCCESS == lerr)
  307. {
  308. if (REG_SZ != dwRegEntType)
  309. {
  310. Win4Assert(L"ThreadingModel Key Type incorrect");
  311. }
  312. else if (0 == lstrcmpiW(wszAptModel, wszModelBuf))
  313. {
  314. //
  315. // An APARTMENT model object.
  316. //
  317. *pulDllThreadType = APT_THREADED;
  318. }
  319. else if (0 == lstrcmpiW(wszBothModel, wszModelBuf))
  320. {
  321. //
  322. // A BOTH model object.
  323. //
  324. *pulDllThreadType = BOTH_THREADED;
  325. }
  326. else if (lstrcmpiW(wszFreeModel, wszModelBuf) == 0)
  327. {
  328. //
  329. // A FREE_THREADED model object.
  330. //
  331. *pulDllThreadType = FREE_THREADED;
  332. }
  333. else if (0 == lstrcmpiW(wszNeutralModel, wszModelBuf))
  334. {
  335. //
  336. // A NEUTRAL_THREADED object.
  337. //
  338. *pulDllThreadType = NEUTRAL_THREADED;
  339. }
  340. else
  341. {
  342. Win4Assert(L"ThreadingModel Value incorrect");
  343. }
  344. }
  345. //
  346. // When we get to this point, we got a DLL entry so we remap
  347. // any errors to success because they only mean that we could
  348. // not get a model from the registry.
  349. //
  350. lerr = ERROR_SUCCESS;
  351. }
  352. }
  353. RegCloseKey(hDllEntry);
  354. }
  355. return lerr;
  356. }