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.

1257 lines
36 KiB

  1. #include "dtctreg.h"
  2. #include "hwdev.h"
  3. #include "pnp.h"
  4. #include "cmmn.h"
  5. #include "sfstr.h"
  6. #include "reg.h"
  7. #include "misc.h"
  8. #include "shobjidl.h"
  9. #include "shpriv.h"
  10. #include "users.h"
  11. #include "strsafe.h"
  12. #include "str.h"
  13. #include "dbg.h"
  14. #include "mischlpr.h"
  15. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  16. HRESULT _GetValueToUse(LPWSTR pszKeyName, LPWSTR psz, DWORD cch)
  17. {
  18. HKEY hkey;
  19. HRESULT hr = _RegOpenKey(HKEY_LOCAL_MACHINE, pszKeyName, &hkey);
  20. if (SUCCEEDED(hr) && (S_FALSE != hr))
  21. {
  22. // For now we take the first one.
  23. hr = _RegEnumStringValue(hkey, 0, psz, cch);
  24. _RegCloseKey(hkey);
  25. }
  26. return hr;
  27. }
  28. // Return Values:
  29. // S_FALSE: Can't find it
  30. HRESULT _GetEventHandlerFromKey(LPCWSTR pszKeyName, LPCWSTR pszEventType,
  31. LPWSTR pszEventHandler, DWORD cchEventHandler)
  32. {
  33. WCHAR szEventHandler[MAX_KEY];
  34. DWORD cchLeft;
  35. LPWSTR pszNext;
  36. HRESULT hr = SafeStrCpyNEx(szEventHandler, pszKeyName,
  37. ARRAYSIZE(szEventHandler), &pszNext, &cchLeft);
  38. if (SUCCEEDED(hr))
  39. {
  40. hr = SafeStrCpyNEx(pszNext, TEXT("\\EventHandlers\\"), cchLeft,
  41. &pszNext, &cchLeft);
  42. if (SUCCEEDED(hr))
  43. {
  44. hr = SafeStrCpyN(pszNext, pszEventType, cchLeft);
  45. if (SUCCEEDED(hr))
  46. {
  47. hr = _GetValueToUse(szEventHandler, pszEventHandler,
  48. cchEventHandler);
  49. }
  50. }
  51. }
  52. return hr;
  53. }
  54. // Return Values:
  55. // S_FALSE: Can't find it
  56. HRESULT _GetEventHandlerFromDeviceHandler(LPCWSTR pszDeviceHandler,
  57. LPCWSTR pszEventType, LPWSTR pszEventHandler, DWORD cchEventHandler)
  58. {
  59. WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("DeviceHandlers\\"));
  60. HRESULT hr = SafeStrCatN(szKeyName, pszDeviceHandler,
  61. ARRAYSIZE(szKeyName));
  62. if (SUCCEEDED(hr))
  63. {
  64. hr = _GetEventHandlerFromKey(szKeyName, pszEventType, pszEventHandler,
  65. cchEventHandler);
  66. }
  67. return hr;
  68. }
  69. HRESULT _GetStuffFromHandlerHelper(LPCWSTR pszHandler, LPCWSTR pszValueName,
  70. LPWSTR psz, DWORD cch)
  71. {
  72. HKEY hkey;
  73. WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("Handlers\\"));
  74. HRESULT hr = _RegOpenKey(HKEY_LOCAL_MACHINE, szKeyName, &hkey);
  75. if (SUCCEEDED(hr) && (S_FALSE != hr))
  76. {
  77. hr = _RegQueryString(hkey, pszHandler,
  78. pszValueName, psz, cch);
  79. _RegCloseKey(hkey);
  80. }
  81. return hr;
  82. }
  83. HRESULT _GetActionFromHandler(LPCWSTR pszHandler, LPWSTR pszAction,
  84. DWORD cchAction)
  85. {
  86. HRESULT hr = _GetStuffFromHandlerHelper(pszHandler, TEXT("Action"),
  87. pszAction, cchAction);
  88. if (SUCCEEDED(hr) && (S_FALSE == hr))
  89. {
  90. hr = _GetStuffFromHandlerHelper(pszHandler, TEXT("FriendlyName"),
  91. pszAction, cchAction);
  92. }
  93. return hr;
  94. }
  95. HRESULT _GetProviderFromHandler(LPCWSTR pszHandler, LPWSTR pszProvider,
  96. DWORD cchProvider)
  97. {
  98. HRESULT hr = _GetStuffFromHandlerHelper(pszHandler, TEXT("Provider"),
  99. pszProvider, cchProvider);
  100. if (SUCCEEDED(hr) && (S_FALSE == hr))
  101. {
  102. hr = SafeStrCpyN(pszProvider, TEXT("<need provider>"), cchProvider);
  103. }
  104. return hr;
  105. }
  106. HRESULT _GetIconLocationFromHandler(LPCWSTR pszHandler,
  107. LPWSTR pszIconLocation, DWORD cchIconLocation)
  108. {
  109. return _GetStuffFromHandlerHelper(pszHandler, TEXT("DefaultIcon"),
  110. pszIconLocation, cchIconLocation);
  111. }
  112. HRESULT _GetInvokeProgIDFromHandler(LPCWSTR pszHandler,
  113. LPWSTR pszInvokeProgID, DWORD cchInvokeProgID)
  114. {
  115. return _GetStuffFromHandlerHelper(pszHandler, TEXT("InvokeProgID"),
  116. pszInvokeProgID, cchInvokeProgID);
  117. }
  118. HRESULT _GetInvokeVerbFromHandler(LPCWSTR pszHandler,
  119. LPWSTR pszInvokeVerb, DWORD cchInvokeVerb)
  120. {
  121. return _GetStuffFromHandlerHelper(pszHandler, TEXT("InvokeVerb"),
  122. pszInvokeVerb, cchInvokeVerb);
  123. }
  124. HRESULT _GetDevicePropertySize(CHWDeviceInst* phwdevinst,
  125. LPCWSTR pszPropName, BOOL fUseMergeMultiSz, DWORD* pcbSize)
  126. {
  127. // Instance
  128. DEVINST devinst;
  129. HRESULT hr = phwdevinst->GetDeviceInstance(&devinst);
  130. if (SUCCEEDED(hr) && (S_FALSE != hr))
  131. {
  132. BYTE rgb[1];
  133. ULONG ulData = sizeof(rgb);
  134. ULONG ulFlags = 0;
  135. if (fUseMergeMultiSz)
  136. {
  137. ulFlags = CM_CUSTOMDEVPROP_MERGE_MULTISZ;
  138. }
  139. CONFIGRET cr = CM_Get_DevNode_Custom_Property(devinst, pszPropName,
  140. NULL, rgb, &ulData, ulFlags);
  141. if (CR_SUCCESS != cr)
  142. {
  143. if (CR_BUFFER_SMALL == cr)
  144. {
  145. hr = S_OK;
  146. *pcbSize = ulData;
  147. }
  148. else
  149. {
  150. // If we do not have the data at the instance level, let's try it
  151. // at the DeviceGroup level.
  152. // DeviceGroup
  153. WCHAR szDeviceGroup[MAX_DEVICEGROUP];
  154. ulData = sizeof(szDeviceGroup);
  155. cr = CM_Get_DevNode_Custom_Property(devinst, TEXT("DeviceGroup"),
  156. NULL, (PBYTE)szDeviceGroup, &ulData, 0);
  157. if (CR_SUCCESS == cr)
  158. {
  159. WCHAR szKey[MAX_KEY] =
  160. SHDEVICEEVENTROOT(TEXT("DeviceGroups\\"));
  161. hr = SafeStrCatN(szKey, szDeviceGroup, ARRAYSIZE(szKey));
  162. if (SUCCEEDED(hr))
  163. {
  164. hr = _GetPropertySizeHelper(szKey, pszPropName,
  165. pcbSize);
  166. }
  167. }
  168. else
  169. {
  170. hr = S_FALSE;
  171. }
  172. }
  173. }
  174. }
  175. if (S_FALSE == hr)
  176. {
  177. // If we do not have the data at the instance level, nor the device
  178. // group level, let's try it at the DeviceClass level.
  179. // DeviceClass
  180. GUID guidInterface;
  181. hr = phwdevinst->GetInterfaceGUID(&guidInterface);
  182. if (SUCCEEDED(hr) && (S_FALSE != hr))
  183. {
  184. WCHAR szKey[MAX_KEY];
  185. LPWSTR pszNext;
  186. DWORD cchLeft;
  187. hr = SafeStrCpyNEx(szKey,
  188. SHDEVICEEVENTROOT(TEXT("DeviceClasses\\")), ARRAYSIZE(szKey),
  189. &pszNext, &cchLeft);
  190. if (SUCCEEDED(hr))
  191. {
  192. hr = _StringFromGUID(&guidInterface, pszNext, cchLeft);
  193. if (SUCCEEDED(hr) && (S_FALSE != hr))
  194. {
  195. hr = _GetPropertySizeHelper(szKey, pszPropName, pcbSize);
  196. }
  197. }
  198. }
  199. }
  200. return hr;
  201. }
  202. HRESULT _GetDevicePropertyGeneric(CHWDeviceInst* phwdevinst,
  203. LPCWSTR pszPropName, BOOL fUseMergeMultiSz, DWORD* pdwType, LPBYTE pbData,
  204. DWORD cbData)
  205. {
  206. // Instance
  207. DEVINST devinst;
  208. HRESULT hr = phwdevinst->GetDeviceInstance(&devinst);
  209. if (CHWEventDetectorHelper::_fDiagnosticAppPresent)
  210. {
  211. WCHAR szPnpID[MAX_PNPID];
  212. WCHAR szGUID[MAX_GUIDSTRING];
  213. GUID guid;
  214. HRESULT hrTmp = phwdevinst->GetPnpID(szPnpID, ARRAYSIZE(szPnpID));
  215. if (SUCCEEDED(hrTmp) && (S_FALSE != hrTmp))
  216. {
  217. DIAGNOSTIC((TEXT("[0269]Device PnP ID: %s"), szPnpID));
  218. }
  219. hrTmp = phwdevinst->GetInterfaceGUID(&guid);
  220. if (SUCCEEDED(hrTmp) && (S_FALSE != hrTmp))
  221. {
  222. hrTmp = _StringFromGUID(&guid, szGUID, ARRAYSIZE(szGUID));
  223. if (SUCCEEDED(hrTmp))
  224. {
  225. DIAGNOSTIC((TEXT("[0270]Device Class ID: %s"), szGUID));
  226. }
  227. }
  228. }
  229. *pdwType = 0;
  230. if (SUCCEEDED(hr) && (S_FALSE != hr))
  231. {
  232. ULONG ulData = cbData;
  233. ULONG ulType;
  234. ULONG ulFlags = 0;
  235. if (fUseMergeMultiSz)
  236. {
  237. ulFlags = CM_CUSTOMDEVPROP_MERGE_MULTISZ;
  238. }
  239. CONFIGRET cr = CM_Get_DevNode_Custom_Property(devinst, pszPropName,
  240. &ulType, pbData, &ulData, ulFlags);
  241. if (CR_SUCCESS != cr)
  242. {
  243. // If we do not have the data at the instance level, let's try it
  244. // at the DeviceGroup level.
  245. // DeviceGroup
  246. WCHAR szDeviceGroup[MAX_DEVICEGROUP];
  247. DIAGNOSTIC((TEXT("[0252]Did NOT get Custom Property (%s) at device instance level"),
  248. pszPropName));
  249. ulData = sizeof(szDeviceGroup);
  250. cr = CM_Get_DevNode_Custom_Property(devinst, TEXT("DeviceGroup"),
  251. NULL, (PBYTE)szDeviceGroup, &ulData, 0);
  252. if (CR_SUCCESS == cr)
  253. {
  254. WCHAR szKey[MAX_KEY] =
  255. SHDEVICEEVENTROOT(TEXT("DeviceGroups\\"));
  256. hr = SafeStrCatN(szKey, szDeviceGroup, ARRAYSIZE(szKey));
  257. if (SUCCEEDED(hr))
  258. {
  259. hr = _GetPropertyHelper(szKey, pszPropName, pdwType,
  260. pbData, cbData);
  261. if (SUCCEEDED(hr))
  262. {
  263. if (S_FALSE != hr)
  264. {
  265. DIAGNOSTIC((TEXT("[0253]Got Custom Property (%s) at DeviceGroup level (%s)"),
  266. pszPropName, szDeviceGroup));
  267. }
  268. else
  269. {
  270. DIAGNOSTIC((TEXT("[0254]Did NOT get Custom Property (%s) at DeviceGroup level (%s)"),
  271. pszPropName, szDeviceGroup));
  272. }
  273. }
  274. }
  275. }
  276. else
  277. {
  278. hr = S_FALSE;
  279. }
  280. }
  281. else
  282. {
  283. DIAGNOSTIC((TEXT("[0251]Got Custom Property (%s) at device instance level"), pszPropName));
  284. *pdwType = (DWORD)ulType;
  285. }
  286. }
  287. if (S_FALSE == hr)
  288. {
  289. // If we do not have the data at the instance level, nor the device
  290. // group level, let's try it at the DeviceClass level.
  291. // DeviceClass
  292. GUID guidInterface;
  293. hr = phwdevinst->GetInterfaceGUID(&guidInterface);
  294. if (SUCCEEDED(hr) && (S_FALSE != hr))
  295. {
  296. WCHAR szKey[MAX_KEY];
  297. LPWSTR pszNext;
  298. DWORD cchLeft;
  299. hr = SafeStrCpyNEx(szKey,
  300. SHDEVICEEVENTROOT(TEXT("DeviceClasses\\")), ARRAYSIZE(szKey),
  301. &pszNext, &cchLeft);
  302. if (SUCCEEDED(hr))
  303. {
  304. hr = _StringFromGUID(&guidInterface, pszNext, cchLeft);
  305. if (SUCCEEDED(hr) && (S_FALSE != hr))
  306. {
  307. hr = _GetPropertyHelper(szKey, pszPropName, pdwType,
  308. pbData, cbData);
  309. if (SUCCEEDED(hr))
  310. {
  311. if (S_FALSE != hr)
  312. {
  313. DIAGNOSTIC((TEXT("[0255]Got Custom Property (%s) at DeviceClass level (%s)"),
  314. pszPropName, pszNext));
  315. }
  316. else
  317. {
  318. DIAGNOSTIC((TEXT("[0256]Did NOT get Custom Property (%s) at DeviceClass level (%s)"),
  319. pszPropName, pszNext));
  320. }
  321. }
  322. }
  323. }
  324. }
  325. }
  326. return hr;
  327. }
  328. HRESULT _GetDevicePropertyAsString(CHWDeviceInst* phwdevinst,
  329. LPCWSTR pszPropName, LPCWSTR psz, DWORD cch)
  330. {
  331. DWORD dwType;
  332. DWORD cbData = cch * sizeof(WCHAR);
  333. return _GetDevicePropertyGeneric(phwdevinst, pszPropName, FALSE, &dwType,
  334. (PBYTE)psz, cbData);
  335. }
  336. HRESULT _GetDevicePropertyGenericAsMultiSz(CHWDeviceInst* phwdevinst,
  337. LPCWSTR pszPropName, BOOL fUseMergeMultiSz, WORD_BLOB** ppblob)
  338. {
  339. DWORD cbSize = NULL;
  340. HRESULT hr = _GetDevicePropertySize(phwdevinst, pszPropName, FALSE,
  341. &cbSize);
  342. *ppblob = NULL;
  343. if (SUCCEEDED(hr) && (S_FALSE != hr))
  344. {
  345. WORD_BLOB* pblob = (WORD_BLOB*)CoTaskMemAlloc(
  346. sizeof(WORD_BLOB) + cbSize + sizeof(WCHAR));
  347. if (pblob)
  348. {
  349. DWORD dwType;
  350. DWORD cbSize2 = cbSize + sizeof(WCHAR);
  351. pblob->clSize = (cbSize + sizeof(WCHAR))/2;
  352. hr = _GetDevicePropertyGeneric(phwdevinst, pszPropName,
  353. fUseMergeMultiSz, &dwType, (PBYTE)(pblob->asData),
  354. cbSize2);
  355. if (SUCCEEDED(hr) && (S_FALSE != hr))
  356. {
  357. if (REG_MULTI_SZ == dwType)
  358. {
  359. DIAGNOSTIC((TEXT("[0265]Found Property: '%s'"), pszPropName));
  360. *ppblob = pblob;
  361. pblob = NULL;
  362. }
  363. else
  364. {
  365. DIAGNOSTIC((TEXT("[0266]Found Property: '%s', but NOT REG_MULTI_SZ type"), pszPropName));
  366. hr = E_FAIL;
  367. }
  368. }
  369. if (pblob)
  370. {
  371. // It did not get assigned
  372. CoTaskMemFree(pblob);
  373. }
  374. }
  375. else
  376. {
  377. hr = E_OUTOFMEMORY;
  378. }
  379. }
  380. return hr;
  381. }
  382. HRESULT _GetDevicePropertyGenericAsBlob(CHWDeviceInst* phwdevinst,
  383. LPCWSTR pszPropName, BYTE_BLOB** ppblob)
  384. {
  385. DWORD cbSize = NULL;
  386. HRESULT hr = _GetDevicePropertySize(phwdevinst, pszPropName, FALSE,
  387. &cbSize);
  388. *ppblob = NULL;
  389. if (SUCCEEDED(hr) && (S_FALSE != hr))
  390. {
  391. BYTE_BLOB* pblob = (BYTE_BLOB*)CoTaskMemAlloc(
  392. sizeof(BYTE_BLOB) + cbSize);
  393. if (pblob)
  394. {
  395. DWORD dwType;
  396. pblob->clSize = cbSize;
  397. hr = _GetDevicePropertyGeneric(phwdevinst, pszPropName,
  398. FALSE, &dwType, (PBYTE)pblob->abData, pblob->clSize);
  399. if (SUCCEEDED(hr) && (S_FALSE != hr))
  400. {
  401. if (REG_BINARY == dwType)
  402. {
  403. DIAGNOSTIC((TEXT("[0267]Found Property: '%s'"), pszPropName));
  404. *ppblob = pblob;
  405. pblob = NULL;
  406. }
  407. else
  408. {
  409. DIAGNOSTIC((TEXT("[0268]Found Property: '%s', but NOT REG_BINARY type"), pszPropName));
  410. hr = E_FAIL;
  411. }
  412. }
  413. if (pblob)
  414. {
  415. // It did not get assigned
  416. CoTaskMemFree(pblob);
  417. }
  418. }
  419. else
  420. {
  421. hr = E_OUTOFMEMORY;
  422. }
  423. }
  424. return hr;
  425. }
  426. HRESULT _GetDevicePropertyStringNoBuf(CHWDeviceInst* phwdevinst,
  427. LPCWSTR pszPropName, BOOL fUseMergeMultiSz, DWORD* pdwType,
  428. LPWSTR* ppszProp)
  429. {
  430. DWORD cbSize = NULL;
  431. HRESULT hr = _GetDevicePropertySize(phwdevinst, pszPropName, FALSE,
  432. &cbSize);
  433. *ppszProp = NULL;
  434. if (SUCCEEDED(hr) && (S_FALSE != hr))
  435. {
  436. LPWSTR psz;
  437. cbSize += sizeof(WCHAR);
  438. psz = (LPWSTR)CoTaskMemAlloc(cbSize);
  439. if (psz)
  440. {
  441. hr = _GetDevicePropertyGeneric(phwdevinst, pszPropName,
  442. fUseMergeMultiSz, pdwType, (PBYTE)psz, cbSize);
  443. if (FAILED(hr) || (S_FALSE == hr))
  444. {
  445. CoTaskMemFree(psz);
  446. }
  447. else
  448. {
  449. *ppszProp = psz;
  450. }
  451. }
  452. else
  453. {
  454. hr = E_OUTOFMEMORY;
  455. }
  456. }
  457. return hr;
  458. }
  459. // Return Values:
  460. // S_FALSE: Can't find it
  461. HRESULT _GetDeviceHandler(CHWDeviceInst* phwdevinst, LPWSTR pszDeviceHandler,
  462. DWORD cchDeviceHandler)
  463. {
  464. return _GetDevicePropertyAsString(phwdevinst, TEXT("DeviceHandlers"),
  465. pszDeviceHandler, cchDeviceHandler);
  466. }
  467. ///////////////////////////////////////////////////////////////////////////////
  468. //
  469. HRESULT _OpenHandlerRegKey(LPCWSTR pszHandler, HKEY* phkey)
  470. {
  471. WCHAR szKey[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("Handlers\\"));
  472. HRESULT hr = SafeStrCatN(szKey, pszHandler, ARRAYSIZE(szKey));
  473. if (SUCCEEDED(hr))
  474. {
  475. hr = _RegOpenKey(HKEY_LOCAL_MACHINE, szKey, phkey);
  476. }
  477. return hr;
  478. }
  479. HRESULT _CloseHandlerRegKey(HKEY hkey)
  480. {
  481. return _RegCloseKey(hkey);
  482. }
  483. HRESULT _GetHandlerCancelCLSID(LPCWSTR pszHandler, CLSID* pclsid)
  484. {
  485. HKEY hkey;
  486. HRESULT hr = _OpenHandlerRegKey(pszHandler, &hkey);
  487. if (SUCCEEDED(hr))
  488. {
  489. WCHAR szProgID[MAX_PROGID];
  490. hr = _RegQueryString(hkey, NULL, TEXT("CLSIDForCancel"), szProgID,
  491. ARRAYSIZE(szProgID));
  492. if (SUCCEEDED(hr))
  493. {
  494. if (S_FALSE != hr)
  495. {
  496. hr = _GUIDFromString(szProgID, pclsid);
  497. DIAGNOSTIC((TEXT("[0162]Got Handler Cancel CLSID (from CLSIDForCancel): %s"), szProgID));
  498. TRACE(TF_SHHWDTCTDTCTREG, TEXT("Got Handler Cancel CLSID"));
  499. }
  500. else
  501. {
  502. hr = _GetHandlerCLSID(pszHandler, pclsid);
  503. if (CHWEventDetectorHelper::_fDiagnosticAppPresent)
  504. {
  505. if (SUCCEEDED(hr))
  506. {
  507. if (S_FALSE != hr)
  508. {
  509. hr = _StringFromGUID(pclsid, szProgID, ARRAYSIZE(szProgID));
  510. if (SUCCEEDED(hr))
  511. {
  512. DIAGNOSTIC((TEXT("[0164]Got Handler Cancel CLSID: %s"), szProgID));
  513. }
  514. }
  515. }
  516. }
  517. }
  518. }
  519. _CloseHandlerRegKey(hkey);
  520. }
  521. return hr;
  522. }
  523. HRESULT _GetHandlerCLSID(LPCWSTR pszHandler, CLSID* pclsid)
  524. {
  525. HKEY hkey;
  526. HRESULT hr = _OpenHandlerRegKey(pszHandler, &hkey);
  527. if (SUCCEEDED(hr))
  528. {
  529. WCHAR szProgID[MAX_PROGID];
  530. hr = _RegQueryString(hkey, NULL, TEXT("ProgID"), szProgID,
  531. ARRAYSIZE(szProgID));
  532. if (SUCCEEDED(hr))
  533. {
  534. if (S_FALSE != hr)
  535. {
  536. hr = CLSIDFromProgID(szProgID, pclsid);
  537. DIAGNOSTIC((TEXT("[0160]Got Handler ProgID: %s"), szProgID));
  538. TRACE(TF_SHHWDTCTDTCTREG, TEXT("Got Handler ProgID: %s"),
  539. szProgID);
  540. }
  541. else
  542. {
  543. // Not there, maybe we have CLSID value?
  544. // Reuse szProgID
  545. hr = _RegQueryString(hkey, NULL, TEXT("CLSID"), szProgID,
  546. ARRAYSIZE(szProgID));
  547. if (SUCCEEDED(hr) && (S_FALSE != hr))
  548. {
  549. hr = _GUIDFromString(szProgID, pclsid);
  550. DIAGNOSTIC((TEXT("[0161]Got Handler CLSID: %s"), szProgID));
  551. TRACE(TF_SHHWDTCTDTCTREG, TEXT("Got Handler CLSID"));
  552. }
  553. else
  554. {
  555. DIAGNOSTIC((TEXT("[0163]Did NOT get Handler ProgID or CLSID")));
  556. }
  557. }
  558. }
  559. _CloseHandlerRegKey(hkey);
  560. }
  561. return hr;
  562. }
  563. // Return values:
  564. // S_FALSE: Cannot find an InitCmdLine
  565. //
  566. HRESULT _GetInitCmdLine(LPCWSTR pszHandler, LPWSTR* ppsz)
  567. {
  568. HKEY hkey;
  569. HRESULT hr = _OpenHandlerRegKey(pszHandler, &hkey);
  570. *ppsz = NULL;
  571. if (SUCCEEDED(hr))
  572. {
  573. DWORD cb = NULL;
  574. hr = _RegQueryValueSize(hkey, NULL, TEXT("InitCmdLine"), &cb);
  575. if (SUCCEEDED(hr) && (S_FALSE != hr))
  576. {
  577. LPWSTR psz = (LPWSTR)LocalAlloc(LPTR, cb);
  578. if (psz)
  579. {
  580. hr = _RegQueryString(hkey, NULL, TEXT("InitCmdLine"), psz,
  581. cb / sizeof(WCHAR));
  582. if (SUCCEEDED(hr) && (S_FALSE != hr))
  583. {
  584. DIAGNOSTIC((TEXT("[0158]Got InitCmdLine for Handler (%s): '%s'"), pszHandler, psz));
  585. *ppsz = psz;
  586. }
  587. else
  588. {
  589. LocalFree((HLOCAL)psz);
  590. }
  591. }
  592. else
  593. {
  594. hr = E_OUTOFMEMORY;
  595. }
  596. }
  597. else
  598. {
  599. DIAGNOSTIC((TEXT("[0159]NO InitCmdLine for Handler (%s)"), pszHandler));
  600. }
  601. _CloseHandlerRegKey(hkey);
  602. }
  603. return hr;
  604. }
  605. HRESULT _MakeUserDefaultValueString(LPCWSTR pszDeviceID,
  606. LPCWSTR pszEventHandler, LPWSTR pszUserDefault, DWORD cchUserDefault)
  607. {
  608. DWORD cchLeft;
  609. LPWSTR pszNext;
  610. HRESULT hr = SafeStrCpyNEx(pszUserDefault, pszDeviceID, cchUserDefault,
  611. &pszNext, &cchLeft);
  612. if (SUCCEEDED(hr))
  613. {
  614. hr = SafeStrCpyNEx(pszNext, TEXT("+"), cchLeft, &pszNext, &cchLeft);
  615. if (SUCCEEDED(hr))
  616. {
  617. hr = SafeStrCpyN(pszNext, pszEventHandler, cchLeft);
  618. }
  619. }
  620. return hr;
  621. }
  622. // from setenum.cpp
  623. HRESULT _GetKeyLastWriteTime(LPCWSTR pszHandler, FILETIME* pft);
  624. HRESULT _HaveNewHandlersBeenInstalledSinceUserSelection(LPCWSTR pszEventHandler,
  625. FILETIME* pftUserSelection, BOOL* pfNewHandlersSinceUserSelection)
  626. {
  627. WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("EventHandlers\\"));
  628. HRESULT hr = SafeStrCatN(szKeyName, pszEventHandler,
  629. ARRAYSIZE(szKeyName));
  630. ULARGE_INTEGER ulUserSelection;
  631. ulUserSelection.LowPart = pftUserSelection->dwLowDateTime;
  632. ulUserSelection.HighPart = pftUserSelection->dwHighDateTime;
  633. *pfNewHandlersSinceUserSelection = FALSE;
  634. if (SUCCEEDED(hr))
  635. {
  636. HKEY hkey;
  637. hr = _RegOpenKey(HKEY_LOCAL_MACHINE, szKeyName, &hkey);
  638. if (SUCCEEDED(hr) && (S_FALSE != hr))
  639. {
  640. DWORD dw = 0;
  641. BOOL fGoOut = FALSE;
  642. do
  643. {
  644. WCHAR szHandler[MAX_HANDLER];
  645. hr = _RegEnumStringValue(hkey, dw, szHandler,
  646. ARRAYSIZE(szHandler));
  647. if (SUCCEEDED(hr) && (S_FALSE != hr))
  648. {
  649. FILETIME ft;
  650. hr = _GetKeyLastWriteTime(szHandler, &ft);
  651. if (SUCCEEDED(hr) && (S_FALSE != hr))
  652. {
  653. ULARGE_INTEGER ul;
  654. ul.LowPart = ft.dwLowDateTime;
  655. ul.HighPart = ft.dwHighDateTime;
  656. if (ul.QuadPart > ulUserSelection.QuadPart)
  657. {
  658. *pfNewHandlersSinceUserSelection = TRUE;
  659. hr = S_OK;
  660. fGoOut = TRUE;
  661. }
  662. }
  663. }
  664. else
  665. {
  666. fGoOut = TRUE;
  667. }
  668. ++dw;
  669. }
  670. while (!fGoOut);
  671. if (S_FALSE == hr)
  672. {
  673. hr = S_OK;
  674. }
  675. _RegCloseKey(hkey);
  676. }
  677. }
  678. return hr;
  679. }
  680. struct _USERSELECTIONHIDDENDATA
  681. {
  682. _USERSELECTIONHIDDENDATA() : dw(0) {}
  683. FILETIME ft;
  684. // Set this to zero so that RegSetValueEx will not NULL terminate out stuff
  685. DWORD dw;
  686. };
  687. // See comment for _MakeFinalUserDefaultHandler
  688. HRESULT _GetHandlerAndFILETIME(HKEY hkeyUser, LPCWSTR pszKeyName,
  689. LPCWSTR pszUserDefault, LPWSTR pszHandler, DWORD cchHandler, FILETIME* pft)
  690. {
  691. DWORD cb;
  692. HRESULT hr = _RegQueryValueSize(hkeyUser, pszKeyName, pszUserDefault, &cb);
  693. if (SUCCEEDED(hr) && (S_FALSE != hr))
  694. {
  695. BYTE* pb = (BYTE*)LocalAlloc(LPTR, cb);
  696. if (pb)
  697. {
  698. DWORD dwType;
  699. hr = _RegQueryGenericWithType(hkeyUser, pszKeyName, pszUserDefault,
  700. &dwType, pb, cb);
  701. if (SUCCEEDED(hr) && (S_FALSE != hr))
  702. {
  703. // We should have something like this:
  704. // MyHandler\0<_USERSELECTIONHIDDENDATA struct>
  705. hr = StringCchCopy(pszHandler, cchHandler, (LPWSTR)pb);
  706. if (SUCCEEDED(hr))
  707. {
  708. DWORD cbString = (lstrlen(pszHandler) + 1) * sizeof(WCHAR);
  709. // Make sure we're dealing with the right thing
  710. if ((cb >= cbString + sizeof(_USERSELECTIONHIDDENDATA)) &&
  711. (cb <= cbString + sizeof(_USERSELECTIONHIDDENDATA) + sizeof(void*)))
  712. {
  713. // Yep! So _USERSELECTIONHIDDENDATA should be at the end of the blob
  714. _USERSELECTIONHIDDENDATA* pushd = (_USERSELECTIONHIDDENDATA*)
  715. (pb + (cb - sizeof(_USERSELECTIONHIDDENDATA)));
  716. *pft = pushd->ft;
  717. }
  718. else
  719. {
  720. *pszHandler = 0;
  721. hr = S_FALSE;
  722. }
  723. }
  724. }
  725. LocalFree(pb);
  726. }
  727. else
  728. {
  729. hr = E_OUTOFMEMORY;
  730. }
  731. }
  732. return hr;
  733. }
  734. HRESULT _GetEventHandlerDefault(HKEY hkeyUser, LPCWSTR pszEventHandler,
  735. LPWSTR pszHandler, DWORD cchHandler)
  736. {
  737. WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("EventHandlersDefaultSelection\\"));
  738. return _RegQueryString(hkeyUser, szKeyName, pszEventHandler, pszHandler,
  739. cchHandler);
  740. }
  741. HRESULT _GetUserDefaultHandler(LPCWSTR pszDeviceID, LPCWSTR pszEventHandler,
  742. LPWSTR pszHandler, DWORD cchHandler, BOOL fImpersonateCaller)
  743. {
  744. WCHAR szUserDefault[MAX_USERDEFAULT] = TEXT("H:");
  745. HRESULT hr = _MakeUserDefaultValueString(pszDeviceID, pszEventHandler,
  746. &(szUserDefault[2]), ARRAYSIZE(szUserDefault) - 2);
  747. if (cchHandler)
  748. {
  749. *pszHandler = 0;
  750. }
  751. if (SUCCEEDED(hr))
  752. {
  753. WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("UserChosenExecuteHandlers\\"));
  754. HKEY hkeyUser;
  755. HANDLE hThreadToken;
  756. if (GUH_IMPERSONATEUSER == fImpersonateCaller)
  757. {
  758. hr = _CoGetCallingUserHKCU(&hThreadToken, &hkeyUser);
  759. }
  760. else
  761. {
  762. hr = _GetCurrentUserHKCU(&hThreadToken, &hkeyUser);
  763. }
  764. if (SUCCEEDED(hr) && (S_FALSE != hr))
  765. {
  766. FILETIME ft;
  767. DWORD dwHandlerDefaultFlag = 0;
  768. hr = _GetHandlerAndFILETIME(hkeyUser, szKeyName,
  769. szUserDefault, pszHandler, cchHandler, &ft);
  770. if (SUCCEEDED(hr))
  771. {
  772. if (S_FALSE == hr)
  773. {
  774. // we do not have a UserChosenDefault
  775. hr = SafeStrCpyN(pszHandler, TEXT("MSPromptEachTime"),
  776. cchHandler);
  777. }
  778. else
  779. {
  780. // we have a user chosen default
  781. dwHandlerDefaultFlag |= HANDLERDEFAULT_USERCHOSENDEFAULT;
  782. }
  783. }
  784. if (SUCCEEDED(hr))
  785. {
  786. if (HANDLERDEFAULT_USERCHOSENDEFAULT & dwHandlerDefaultFlag)
  787. {
  788. BOOL fNewHandlersSinceUserSelection;
  789. hr = _HaveNewHandlersBeenInstalledSinceUserSelection(
  790. pszEventHandler, &ft, &fNewHandlersSinceUserSelection);
  791. if (SUCCEEDED(hr))
  792. {
  793. if (fNewHandlersSinceUserSelection)
  794. {
  795. dwHandlerDefaultFlag |=
  796. HANDLERDEFAULT_MORERECENTHANDLERSINSTALLED;
  797. }
  798. }
  799. }
  800. }
  801. if (SUCCEEDED(hr))
  802. {
  803. BOOL fUseEventHandlerDefault = FALSE;
  804. if (!(HANDLERDEFAULT_USERCHOSENDEFAULT & dwHandlerDefaultFlag))
  805. {
  806. fUseEventHandlerDefault = TRUE;
  807. }
  808. else
  809. {
  810. if (HANDLERDEFAULT_MORERECENTHANDLERSINSTALLED &
  811. dwHandlerDefaultFlag)
  812. {
  813. fUseEventHandlerDefault = TRUE;
  814. }
  815. }
  816. if (fUseEventHandlerDefault)
  817. {
  818. WCHAR szHandlerLocal[MAX_HANDLER];
  819. hr = _GetEventHandlerDefault(hkeyUser, pszEventHandler,
  820. szHandlerLocal, ARRAYSIZE(szHandlerLocal));
  821. if (SUCCEEDED(hr))
  822. {
  823. if (S_FALSE != hr)
  824. {
  825. dwHandlerDefaultFlag |=
  826. HANDLERDEFAULT_EVENTHANDLERDEFAULT;
  827. if (HANDLERDEFAULT_USERCHOSENDEFAULT &
  828. dwHandlerDefaultFlag)
  829. {
  830. if (lstrcmp(szHandlerLocal, pszHandler))
  831. {
  832. dwHandlerDefaultFlag |=
  833. HANDLERDEFAULT_DEFAULTSAREDIFFERENT;
  834. }
  835. }
  836. else
  837. {
  838. dwHandlerDefaultFlag |=
  839. HANDLERDEFAULT_DEFAULTSAREDIFFERENT;
  840. }
  841. hr = StringCchCopy(pszHandler, cchHandler,
  842. szHandlerLocal);
  843. }
  844. }
  845. }
  846. }
  847. if (SUCCEEDED(hr))
  848. {
  849. // Let's build the return value
  850. hr = HANDLERDEFAULT_MAKERETURNVALUE(dwHandlerDefaultFlag);
  851. }
  852. if (GUH_IMPERSONATEUSER == fImpersonateCaller)
  853. {
  854. _CoCloseCallingUserHKCU(hThreadToken, hkeyUser);
  855. }
  856. else
  857. {
  858. _CloseCurrentUserHKCU(hThreadToken, hkeyUser);
  859. }
  860. }
  861. }
  862. return hr;
  863. }
  864. HRESULT _GetHandlerForNoContent(LPCWSTR pszEventHandler, LPWSTR pszHandler,
  865. DWORD cchHandler)
  866. {
  867. WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("EventHandlers\\"));
  868. HRESULT hr = SafeStrCatN(szKeyName, pszEventHandler, ARRAYSIZE(szKeyName));
  869. if (SUCCEEDED(hr))
  870. {
  871. hr = _GetValueToUse(szKeyName, pszHandler, cchHandler);
  872. }
  873. return hr;
  874. }
  875. // We want to store the time this default is set. We'll need it to check if
  876. // other handlers for this event were installed after the user made a choice.
  877. // If that's the case, we'll reprompt the user.
  878. // *!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!
  879. // We store the time as a FILETIME *after* the '\0' string terminator. This is
  880. // so it will be hidden in RegEdit.
  881. // stephstm (2002-04-12)
  882. // *!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!
  883. HRESULT _MakeFinalUserDefaultHandler(LPCWSTR pszHandler, BYTE** ppb,
  884. DWORD* pcb)
  885. {
  886. HRESULT hr;
  887. DWORD cch = lstrlen(pszHandler) + 1;
  888. DWORD cbOffset = cch * sizeof(WCHAR);
  889. // Round up to be aligned on all platforms
  890. cbOffset = (cbOffset + sizeof(void*)) / sizeof(void*) * sizeof(void*);
  891. DWORD cb = cbOffset + sizeof(_USERSELECTIONHIDDENDATA);
  892. BYTE* pb = (BYTE*)LocalAlloc(LPTR, cb);
  893. if (pb)
  894. {
  895. hr = StringCchCopy((LPWSTR)pb, cch, pszHandler);
  896. if (SUCCEEDED(hr))
  897. {
  898. _USERSELECTIONHIDDENDATA ushd;
  899. GetSystemTimeAsFileTime(&(ushd.ft));
  900. CopyMemory(pb + cb - sizeof(_USERSELECTIONHIDDENDATA), &ushd,
  901. sizeof(ushd));
  902. }
  903. if (SUCCEEDED(hr))
  904. {
  905. *ppb = pb;
  906. *pcb = cb;
  907. }
  908. else
  909. {
  910. LocalFree(pb);
  911. }
  912. }
  913. else
  914. {
  915. hr = E_OUTOFMEMORY;
  916. }
  917. return hr;
  918. }
  919. HRESULT _DeleteUserDefaultHandler(HKEY hkeyUser, LPCWSTR pszDeviceID,
  920. LPCWSTR pszEventHandler)
  921. {
  922. WCHAR szUserDefault[MAX_USERDEFAULT] = TEXT("H:");
  923. HRESULT hr = _MakeUserDefaultValueString(pszDeviceID, pszEventHandler,
  924. &(szUserDefault[2]), ARRAYSIZE(szUserDefault) - 2);
  925. if (SUCCEEDED(hr))
  926. {
  927. WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("UserChosenExecuteHandlers\\"));
  928. hr = _RegDeleteValue(hkeyUser, szKeyName, szUserDefault);
  929. }
  930. return hr;
  931. }
  932. HRESULT _SetSoftUserDefaultHandler(LPCWSTR pszDeviceID,
  933. LPCWSTR pszEventHandler, LPCWSTR pszHandler)
  934. {
  935. HKEY hkey;
  936. WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("EventHandlersDefaultSelection\\"));
  937. HKEY hkeyUser;
  938. HANDLE hThreadToken;
  939. HRESULT hr = _CoGetCallingUserHKCU(&hThreadToken, &hkeyUser);
  940. if (SUCCEEDED(hr) && (S_FALSE != hr))
  941. {
  942. DWORD dwDisp;
  943. hr = _RegCreateKey(hkeyUser, szKeyName, &hkey, &dwDisp);
  944. if (SUCCEEDED(hr) && (S_FALSE != hr))
  945. {
  946. hr = _RegSetString(hkey, pszEventHandler, pszHandler);
  947. _DeleteUserDefaultHandler(hkeyUser, pszDeviceID, pszEventHandler);
  948. _RegCloseKey(hkey);
  949. }
  950. _CoCloseCallingUserHKCU(hThreadToken, hkeyUser);
  951. }
  952. return hr;
  953. }
  954. HRESULT _DeleteSoftUserDefaultHandler(HKEY hkeyUser, LPCWSTR pszEventHandler)
  955. {
  956. WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("EventHandlersDefaultSelection\\"));
  957. return _RegDeleteValue(hkeyUser, szKeyName, pszEventHandler);
  958. }
  959. HRESULT _SetUserDefaultHandler(LPCWSTR pszDeviceID, LPCWSTR pszEventHandler,
  960. LPCWSTR pszHandler)
  961. {
  962. WCHAR szUserDefault[MAX_USERDEFAULT] = TEXT("H:");
  963. HRESULT hr = _MakeUserDefaultValueString(pszDeviceID, pszEventHandler,
  964. &(szUserDefault[2]), ARRAYSIZE(szUserDefault) - 2);
  965. if (SUCCEEDED(hr))
  966. {
  967. HKEY hkey;
  968. WCHAR szKeyName[MAX_KEY] = SHDEVICEEVENTROOT(TEXT("UserChosenExecuteHandlers\\"));
  969. HKEY hkeyUser;
  970. HANDLE hThreadToken;
  971. hr = _CoGetCallingUserHKCU(&hThreadToken, &hkeyUser);
  972. if (SUCCEEDED(hr) && (S_FALSE != hr))
  973. {
  974. if (!lstrcmp(pszHandler, TEXT("MSPromptEachTime")))
  975. {
  976. hr = _DeleteUserDefaultHandler(hkeyUser, pszDeviceID,
  977. pszEventHandler);
  978. }
  979. else
  980. {
  981. DWORD dwDisp;
  982. hr = _RegCreateKey(hkeyUser, szKeyName, &hkey, &dwDisp);
  983. if (SUCCEEDED(hr) && (S_FALSE != hr))
  984. {
  985. BYTE* pb;
  986. DWORD cb;
  987. hr = _MakeFinalUserDefaultHandler(pszHandler, &pb, &cb);
  988. if (SUCCEEDED(hr))
  989. {
  990. // See comment above _MakeFinalUserDefaultHandler
  991. // StephStm: 2002-04-09
  992. if (ERROR_SUCCESS == RegSetValueEx(hkey, szUserDefault, 0,
  993. REG_SZ, pb, cb))
  994. {
  995. _DeleteSoftUserDefaultHandler(hkeyUser,
  996. pszEventHandler);
  997. hr = S_OK;
  998. }
  999. else
  1000. {
  1001. hr = S_FALSE;
  1002. }
  1003. LocalFree(pb);
  1004. }
  1005. _RegCloseKey(hkey);
  1006. }
  1007. }
  1008. _CoCloseCallingUserHKCU(hThreadToken, hkeyUser);
  1009. }
  1010. }
  1011. return hr;
  1012. }
  1013. ///////////////////////////////////////////////////////////////////////////////
  1014. //