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.

407 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. // If the value type is REG_EXPAND_SZ then do environment variable
  207. // expansion
  208. if (dwType == REG_EXPAND_SZ)
  209. {
  210. // Expand any embedded environemnt variable expressions
  211. WCHAR wszTemp[MAX_PATH];
  212. lstrcpyW(wszTemp, pwszValue);
  213. *pcbValue = ExpandEnvironmentStrings(wszTemp, pwszValue,MAX_PATH);
  214. }
  215. }
  216. //
  217. // Only close the sub key if we actually opened it.
  218. //
  219. if (hSubKey != hKey)
  220. {
  221. RegCloseKey(hSubKey);
  222. }
  223. }
  224. return lErr;
  225. }
  226. //+-------------------------------------------------------------------------
  227. //
  228. // Function: GetDllInfo
  229. //
  230. // Synopsis: Get the DLL information for a 32 bit DLL
  231. //
  232. // Arguments: [hClsRegEntry] - class handle
  233. // [pwszKey] - key to open
  234. // [pwszDllName] - where to return DLL path
  235. // [pclDllName] - length of above buffer
  236. // [pulDllThreadType] - where to return DLL threading information
  237. //
  238. // Returns: ERROR_SUCCESS - read DLL path information
  239. // Other - registry entries could not be found
  240. //
  241. // Algorithm: Open the DLL key. Then read the DLL path name. Finally read
  242. // the threading model information if it is specified.
  243. //
  244. // History: 09-Nov-94 Ricksa Created
  245. //
  246. //--------------------------------------------------------------------------
  247. LONG wGetDllInfo(
  248. HKEY hClsRegEntry,
  249. LPCWSTR pwszKey,
  250. LPWSTR pwszDllName,
  251. LONG* pclDllName,
  252. ULONG* pulDllThreadType)
  253. {
  254. HKEY hDllEntry = NULL;
  255. //
  256. // Attempt to open the specified registry key.
  257. //
  258. LONG lerr = RegOpenKeyExW(hClsRegEntry, pwszKey, 0, KEY_READ, &hDllEntry);
  259. if (ERROR_SUCCESS == lerr)
  260. {
  261. //
  262. // Try to read the DLL name.
  263. //
  264. lerr = wQueryStripRegValue(hDllEntry, NULL, pwszDllName, pclDllName);
  265. if (ERROR_SUCCESS == lerr)
  266. {
  267. //
  268. // A DLL name is registered. If the DLL is OLE32.DLL, then we
  269. // know all about and don't have to dig more info from the
  270. // the registry. Otherwise, we do need to keep digging.
  271. //
  272. if (wCompareDllName(pwszDllName, OLE32_DLL, OLE32_CHAR_LEN))
  273. {
  274. memcpy(pwszDllName, OLE32_DLL, OLE32_BYTE_LEN);
  275. *pclDllName = OLE32_CHAR_LEN;
  276. *pulDllThreadType = BOTH_THREADED;
  277. }
  278. else
  279. {
  280. //
  281. // Assume there is no registry entry.
  282. //
  283. *pulDllThreadType = SINGLE_THREADED;
  284. //
  285. // Buffer to hold entry for the registry data.
  286. //
  287. WCHAR wszModelBuf[MAX_PATH];
  288. DWORD cdwModelBuf = sizeof(wszModelBuf);
  289. DWORD dwRegEntType;
  290. //
  291. // Read the DLL threading model from the registry.
  292. //
  293. lerr = RegQueryValueExW(hDllEntry,
  294. wszDllThreadModel,
  295. NULL,
  296. &dwRegEntType,
  297. (LPBYTE) &wszModelBuf[0],
  298. &cdwModelBuf);
  299. //
  300. // If there is a thread model descriptor, set the thread
  301. // type accordingly.
  302. //
  303. if (ERROR_SUCCESS == lerr)
  304. {
  305. if (REG_SZ != dwRegEntType)
  306. {
  307. Win4Assert(L"ThreadingModel Key Type incorrect");
  308. }
  309. else if (0 == lstrcmpiW(wszAptModel, wszModelBuf))
  310. {
  311. //
  312. // An APARTMENT model object.
  313. //
  314. *pulDllThreadType = APT_THREADED;
  315. }
  316. else if (0 == lstrcmpiW(wszBothModel, wszModelBuf))
  317. {
  318. //
  319. // A BOTH model object.
  320. //
  321. *pulDllThreadType = BOTH_THREADED;
  322. }
  323. else if (lstrcmpiW(wszFreeModel, wszModelBuf) == 0)
  324. {
  325. //
  326. // A FREE_THREADED model object.
  327. //
  328. *pulDllThreadType = FREE_THREADED;
  329. }
  330. else if (0 == lstrcmpiW(wszNeutralModel, wszModelBuf))
  331. {
  332. //
  333. // A NEUTRAL_THREADED object.
  334. //
  335. *pulDllThreadType = NEUTRAL_THREADED;
  336. }
  337. else
  338. {
  339. Win4Assert(L"ThreadingModel Value incorrect");
  340. }
  341. }
  342. //
  343. // When we get to this point, we got a DLL entry so we remap
  344. // any errors to success because they only mean that we could
  345. // not get a model from the registry.
  346. //
  347. lerr = ERROR_SUCCESS;
  348. }
  349. }
  350. RegCloseKey(hDllEntry);
  351. }
  352. return lerr;
  353. }