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.

2519 lines
80 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. #include "ids.h"
  4. #include "mtptl.h"
  5. #include "hwcmmn.h"
  6. #include "datautil.h"
  7. // for now
  8. #include "mixctnt.h"
  9. #include "filetbl.h"
  10. #include "apprmdlg.h"
  11. #include "views.h"
  12. #include <ddraw.h>
  13. CDPA<PNPNOTIFENTRY> CSniffDrive::_dpaNotifs = NULL;
  14. HANDLE CSniffDrive::_hThreadSCN = NULL;
  15. HWND CSniffDrive::_hwndNotify = NULL;
  16. //
  17. // if a drive has a AutoRun.inf file and AutoRun is not restricted in
  18. // the registry. copy the AutoRun info into a key in the registry.
  19. //
  20. // HKEY_CLASSES_ROOT\AutoRun\0 (0=A,1=B,...)
  21. //
  22. // the key is a standard ProgID key, has DefaultIcon, shell, shellex, ...
  23. //
  24. // the autorun file looks like this....
  25. //
  26. // [AutoRun]
  27. // key = value
  28. // key = value
  29. // key = value
  30. //
  31. // examples:
  32. //
  33. // [AutoRun]
  34. // DefaultIcon = foo.exe,1
  35. // shell=myverb
  36. // shell\myverb = &MyVerb
  37. // shell\myverb\command = myexe.exe
  38. //
  39. // will give the drive a icon from 'foo.exe'
  40. // add a verb called myverb (with name "&My Verb")
  41. // and make myverb default.
  42. //
  43. // [AutoRun]
  44. // shell\myverb = &MyVerb
  45. // shell\myverb\command = myexe.exe
  46. //
  47. // add a verb called myverb (with name "&My Verb")
  48. // verb will not be default.
  49. //
  50. // any thing they add will be copied over, they can add wacky things
  51. // like CLSID's or shellx\ContextMenuHandlers and it will work.
  52. //
  53. // or they can just copy over data the app will look at later.
  54. //
  55. // the following special cases will be supported....
  56. //
  57. // [AutoRun]
  58. // Open = command.exe /params
  59. // Icon = iconfile, iconnumber
  60. //
  61. // will be treated like:
  62. //
  63. // [AutoRun]
  64. // DefaultIcon = iconfile, iconnumber
  65. // shell = AutoRun
  66. // shell\AutoRun = Auto&Play
  67. // shell\AutoRun\command = command.exe /params
  68. //
  69. //
  70. // This function tries to take care of the case that a command was registered
  71. // in the autrun file of a cdrom. If the command is relative than see if the
  72. // command exists on the CDROM
  73. void CMountPoint::_QualifyCommandToDrive(LPTSTR pszCommand, DWORD cchCommand)
  74. {
  75. // for now we assume that we'll call this only for CD mounted on a drive letter
  76. // (by oppoition to a folder)
  77. if (_IsMountedOnDriveLetter())
  78. {
  79. TCHAR szImage[MAX_PATH];
  80. StringCchCopy(szImage, ARRAYSIZE(szImage), pszCommand);
  81. PathRemoveArgs(szImage);
  82. PathUnquoteSpaces(szImage);
  83. if (PathIsRelative(szImage))
  84. {
  85. TCHAR szFinal[MAX_PATH];
  86. LPTSTR pszTmp = szImage;
  87. StringCchCopy(szFinal, ARRAYSIZE(szFinal), _GetName());
  88. // do simple check for command, check for "..\abc" or "../abc"
  89. while ((TEXT('.') == *pszTmp) && (TEXT('.') == *(pszTmp + 1)) &&
  90. ((TEXT('\\') == *(pszTmp + 2)) || (TEXT('/') == *(pszTmp + 2))))
  91. {
  92. pszTmp += 3;
  93. }
  94. StringCchCat(szFinal, ARRAYSIZE(szFinal), pszTmp);
  95. // we first check if it exists on the CD
  96. DWORD dwAttrib = GetFileAttributes(szFinal);
  97. if (0xFFFFFFFF == dwAttrib)
  98. {
  99. // It's not on the CD, try appending ".exe"
  100. StringCchCat(szFinal, ARRAYSIZE(szFinal), TEXT(".exe"));
  101. dwAttrib = GetFileAttributes(szFinal);
  102. }
  103. if (0xFFFFFFFF != dwAttrib)
  104. {
  105. // Yes, it's on the CD
  106. PathQuoteSpaces(szFinal);
  107. LPTSTR pszArgs = PathGetArgs(pszCommand);
  108. if (pszArgs && *pszArgs)
  109. {
  110. StringCchCat(szFinal, ARRAYSIZE(szFinal), pszArgs - 1);
  111. }
  112. StringCchCopy(pszCommand, cchCommand, szFinal);
  113. }
  114. else
  115. {
  116. // No, not on the CD
  117. }
  118. }
  119. }
  120. }
  121. // This one does not hit the drive
  122. BOOL CMountPoint::_IsAutoRunDrive()
  123. {
  124. BOOL fRet = TRUE;
  125. // Add support for now drive letter
  126. if (_IsMountedOnDriveLetter())
  127. {
  128. int iDrive = DRIVEID(_GetName());
  129. // Restrict auto-run's to particular drives.
  130. if (SHRestricted(REST_NODRIVEAUTORUN) & (1 << iDrive))
  131. {
  132. fRet = FALSE;
  133. }
  134. }
  135. if (fRet)
  136. {
  137. UINT uDriveType = _GetDriveType();
  138. // Restrict auto-run's to particular types of drives.
  139. if (SHRestricted(REST_NODRIVETYPEAUTORUN) & (1 << (uDriveType & DRIVE_TYPE)))
  140. {
  141. fRet = FALSE;
  142. }
  143. else
  144. {
  145. if (DRIVE_UNKNOWN == (uDriveType & DRIVE_TYPE))
  146. {
  147. fRet = FALSE;
  148. }
  149. }
  150. if (fRet && _IsFloppy())
  151. {
  152. fRet = FALSE;
  153. }
  154. }
  155. return fRet;
  156. }
  157. HRESULT CMountPoint::_AddAutoplayVerb()
  158. {
  159. HRESULT hr = E_FAIL;
  160. if (RSSetTextValue(TEXT("shell\\Autoplay\\DropTarget"), TEXT("CLSID"),
  161. TEXT("{f26a669a-bcbb-4e37-abf9-7325da15f931}"), REG_OPTION_NON_VOLATILE))
  162. {
  163. // IDS_MENUAUTORUN -> 8504
  164. if (RSSetTextValue(TEXT("shell\\Autoplay"), TEXT("MUIVerb"),
  165. TEXT("@shell32.dll,-8504"), REG_OPTION_NON_VOLATILE))
  166. {
  167. if (RSSetTextValue(TEXT("shell"), NULL, TEXT("None"), REG_OPTION_NON_VOLATILE))
  168. {
  169. hr = S_OK;
  170. }
  171. }
  172. }
  173. return hr;
  174. }
  175. HRESULT CMountPoint::_CopyInvokeVerbKey(LPCWSTR pszProgID, LPCWSTR pszVerb)
  176. {
  177. ASSERT(pszProgID);
  178. ASSERT(pszVerb);
  179. WCHAR szKey[MAX_PATH];
  180. HRESULT hr = E_FAIL;
  181. hr = StringCchPrintf(szKey, ARRAYSIZE(szKey), TEXT("shell\\%s"), pszVerb);
  182. if (SUCCEEDED(hr))
  183. {
  184. hr = E_FAIL;
  185. HKEY hkeyNew = RSDuplicateSubKey(szKey, TRUE, FALSE);
  186. if (hkeyNew)
  187. {
  188. hr = StringCchPrintf(szKey, ARRAYSIZE(szKey), TEXT("%s\\shell\\%s"), pszProgID, pszVerb);
  189. if (SUCCEEDED(hr))
  190. {
  191. hr = E_FAIL;
  192. if (ERROR_SUCCESS == SHCopyKey(HKEY_CLASSES_ROOT, szKey, hkeyNew, 0))
  193. {
  194. if (RSSetTextValue(TEXT("shell"), NULL, pszVerb, REG_OPTION_NON_VOLATILE))
  195. {
  196. hr = S_OK;
  197. }
  198. }
  199. }
  200. RegCloseKey(hkeyNew);
  201. }
  202. }
  203. return hr;
  204. }
  205. BOOL CMountPoint::_ProcessAutoRunFile()
  206. {
  207. BOOL fRet = TRUE;
  208. if (!_fAutorunFileProcessed)
  209. {
  210. BOOL fProcessFile = FALSE;
  211. if (_IsCDROM())
  212. {
  213. CMtPtLocal* pmtptlocal = (CMtPtLocal*)this;
  214. // not CDs with no media, or no autorun.inf files
  215. if (pmtptlocal->_IsMediaPresent())
  216. {
  217. if (!pmtptlocal->_CanUseVolume())
  218. {
  219. fProcessFile = TRUE;
  220. }
  221. else
  222. {
  223. if ((HWDMC_HASAUTORUNINF & pmtptlocal->_pvol->dwMediaCap) &&
  224. !(HWDMC_HASUSEAUTOPLAY & pmtptlocal->_pvol->dwMediaCap))
  225. {
  226. fProcessFile = TRUE;
  227. }
  228. }
  229. }
  230. }
  231. else
  232. {
  233. if (_IsRemote())
  234. {
  235. fProcessFile = TRUE;
  236. }
  237. else
  238. {
  239. if (_IsFixedDisk())
  240. {
  241. fProcessFile = TRUE;
  242. }
  243. }
  244. }
  245. if (fProcessFile)
  246. {
  247. LPCTSTR pszSection;
  248. TCHAR szInfFile[MAX_PATH];
  249. TCHAR szKeys[512];
  250. TCHAR szValue[MAX_PATH];
  251. TCHAR szIcon[MAX_PATH + 12]; // MAX_PATH + room for ",1000000000" (for icon index part)
  252. LPTSTR pszKey;
  253. int iDrive = 0;
  254. RSDeleteSubKey(TEXT("Shell"));
  255. if (_IsMountedOnDriveLetter())
  256. {
  257. iDrive = DRIVEID(_GetName());
  258. }
  259. // build abs path to AutoRun.inf
  260. StringCchCopy(szInfFile, ARRAYSIZE(szInfFile), _GetName());
  261. StringCchCat(szInfFile, ARRAYSIZE(szInfFile), TEXT("AutoRun.inf"));
  262. #if defined(_X86_)
  263. pszSection = TEXT("AutoRun.x86");
  264. #elif defined(_IA64_)
  265. pszSection = TEXT("AutoRun.Ia64");
  266. #elif defined(_AMD64_)
  267. pszSection = TEXT("AutoRun.Amd64");
  268. #endif
  269. //
  270. // make sure a file exists before calling GetPrivateProfileString
  271. // because for some media this check might take a long long time
  272. // and we dont want to have kernel wait wiht the Win16Lock
  273. //
  274. UINT err = SetErrorMode(SEM_FAILCRITICALERRORS);
  275. if (!PathFileExistsAndAttributes(szInfFile, NULL))
  276. {
  277. SetErrorMode(err);
  278. _fAutorunFileProcessed = TRUE;
  279. return FALSE;
  280. }
  281. //
  282. // get all the keys in the [AutoRun] section
  283. //
  284. // Flush the INI cache, or this may fail during a Device broadcast
  285. WritePrivateProfileString(NULL, NULL, NULL, szInfFile);
  286. #if defined(_X86_)
  287. pszSection = TEXT("AutoRun.x86");
  288. #elif defined(_IA64_)
  289. pszSection = TEXT("AutoRun.Ia64");
  290. #endif
  291. int i = GetPrivateProfileString(pszSection, NULL, c_szNULL, szKeys, ARRAYSIZE(szKeys), szInfFile);
  292. // if we fail to find a platform-specific AutoRun section, fall
  293. // back to looking for the naked "AutoRun" section.
  294. if (0 == i)
  295. {
  296. pszSection = TEXT("AutoRun");
  297. i = GetPrivateProfileString(pszSection, NULL, c_szNULL, szKeys, ARRAYSIZE(szKeys), szInfFile);
  298. }
  299. SetErrorMode(err);
  300. if (i >= 4)
  301. {
  302. //
  303. // make sure the external strings are what we think.
  304. //
  305. ASSERT(lstrcmpi(c_szOpen,TEXT("open")) == 0);
  306. ASSERT(lstrcmpi(c_szShell, TEXT("shell")) == 0);
  307. // now walk all the keys in the .inf file and copy them to the registry.
  308. for (pszKey = szKeys; *pszKey; pszKey += lstrlen(pszKey) + 1)
  309. {
  310. GetPrivateProfileString(pszSection, pszKey,
  311. c_szNULL, szValue, ARRAYSIZE(szValue), szInfFile);
  312. //
  313. // special case open =
  314. //
  315. if (lstrcmpi(pszKey, c_szOpen) == 0)
  316. {
  317. if (_IsMountedOnDriveLetter())
  318. {
  319. RSSetTextValue(c_szShell, NULL, TEXT("AutoRun"));
  320. _QualifyCommandToDrive(szValue, ARRAYSIZE(szValue));
  321. RSSetTextValue(TEXT("shell\\AutoRun\\command"), NULL, szValue);
  322. LoadString(HINST_THISDLL, IDS_MENUAUTORUN, szValue, ARRAYSIZE(szValue));
  323. RSSetTextValue(TEXT("shell\\AutoRun"), NULL, szValue);
  324. }
  325. }
  326. //
  327. // special case ShellExecute
  328. //
  329. else if (lstrcmpi(pszKey, TEXT("ShellExecute")) == 0)
  330. {
  331. if (_IsMountedOnDriveLetter())
  332. {
  333. TCHAR szPath[MAX_PATH * 2];
  334. if (ExpandEnvironmentStrings(
  335. TEXT("%windir%\\system32\\RunDLL32.EXE Shell32.DLL,ShellExec_RunDLL "),
  336. szPath, ARRAYSIZE(szPath)))
  337. {
  338. StringCchCat(szPath, ARRAYSIZE(szPath), szValue);
  339. RSSetTextValue(c_szShell, NULL, TEXT("AutoRun"));
  340. RSSetTextValue(TEXT("shell\\AutoRun\\command"), NULL, szPath);
  341. LoadString(HINST_THISDLL, IDS_MENUAUTORUN, szValue, ARRAYSIZE(szValue));
  342. RSSetTextValue(TEXT("shell\\AutoRun"), NULL, szValue);
  343. }
  344. }
  345. }
  346. //
  347. // special case icon =
  348. // make sure the icon file has a full path...
  349. //
  350. else if (lstrcmpi(pszKey, TEXT("Icon")) == 0)
  351. {
  352. StringCchCopy(szIcon, ARRAYSIZE(szIcon), _GetName());
  353. StringCchCat(szIcon, ARRAYSIZE(szIcon), szValue);
  354. RSSetTextValue(TEXT("_Autorun\\DefaultIcon"), NULL, szIcon);
  355. }
  356. //
  357. // special case label =
  358. // make sure the label file has a full path...
  359. //
  360. else if (lstrcmpi(pszKey, TEXT("Label")) == 0)
  361. {
  362. RSSetTextValue(TEXT("_Autorun\\DefaultLabel"), NULL, szValue);
  363. }
  364. //
  365. // special case shell = open
  366. // We have an autorun file but this puts open as the default verb
  367. // so we force it to be Autorun
  368. //
  369. else if (!lstrcmpi(pszKey, TEXT("shell")) && !lstrcmpi(szValue, TEXT("open")))
  370. {
  371. if (_IsMountedOnDriveLetter())
  372. {
  373. RSSetTextValue(pszKey, NULL, TEXT("Autorun"));
  374. }
  375. }
  376. //
  377. // it is just a key/value pair copy it over.
  378. //
  379. else
  380. {
  381. if (_IsMountedOnDriveLetter())
  382. {
  383. if (lstrcmpi(PathFindFileName(pszKey), c_szCommand) == 0)
  384. {
  385. _QualifyCommandToDrive(szValue, ARRAYSIZE(szValue));
  386. }
  387. RSSetTextValue(pszKey, NULL, szValue);
  388. }
  389. }
  390. }
  391. }
  392. else
  393. {
  394. fRet = FALSE;
  395. }
  396. }
  397. _fAutorunFileProcessed = TRUE;
  398. }
  399. return fRet;
  400. }
  401. // sends the "QueryCancelAutoPlay" msg to the window to see if it wants
  402. // to cancel the autoplay. useful for dialogs that are prompting for disk
  403. // inserts or cases where the app wants to capture the event and not let
  404. // other apps be run
  405. // static
  406. BOOL CMountPoint::_AppAllowsAutoRun(HWND hwndApp, CMountPoint* pmtpt)
  407. {
  408. ULONG_PTR dwCancel = 0;
  409. DWORD dwType = pmtpt->_GetAutorunContentType();
  410. WCHAR cDrive = pmtpt->_GetNameFirstCharUCase();
  411. int iDrive = cDrive - TEXT('A');
  412. SendMessageTimeout(hwndApp, QueryCancelAutoPlayMsg(), iDrive, dwType, SMTO_NORMAL | SMTO_ABORTIFHUNG,
  413. 1000, &dwCancel);
  414. return (dwCancel == 0);
  415. }
  416. STDAPI SHCreateQueryCancelAutoPlayMoniker(IMoniker** ppmoniker)
  417. {
  418. return CreateClassMoniker(CLSID_QueryCancelAutoPlay, ppmoniker);
  419. }
  420. struct QUERRYRUNNINGOBJECTSTRUCT
  421. {
  422. WCHAR szMountPoint[MAX_PATH];
  423. DWORD dwContentType;
  424. WCHAR szLabel[MAX_LABEL];
  425. DWORD dwSerialNumber;
  426. };
  427. DWORD WINAPI _QueryRunningObjectThreadProc(void* pv)
  428. {
  429. QUERRYRUNNINGOBJECTSTRUCT* pqro = (QUERRYRUNNINGOBJECTSTRUCT*)pv;
  430. HRESULT hrRet = S_OK;
  431. HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
  432. if (SUCCEEDED(hr))
  433. {
  434. IRunningObjectTable* prot;
  435. hr = GetRunningObjectTable(0, &prot);
  436. if (SUCCEEDED(hr))
  437. {
  438. IMoniker* pmoniker;
  439. IBindCtx* pbindctx;
  440. hr = CreateBindCtx(0, &pbindctx);
  441. if (SUCCEEDED(hr))
  442. {
  443. BIND_OPTS2 bindopts;
  444. ZeroMemory(&bindopts, sizeof(bindopts));
  445. bindopts.cbStruct = sizeof(bindopts);
  446. bindopts.dwClassContext = CLSCTX_LOCAL_SERVER | CLSCTX_NO_CODE_DOWNLOAD;
  447. hr = pbindctx->SetBindOptions(&bindopts);
  448. if (SUCCEEDED(hr))
  449. {
  450. HKEY hkey;
  451. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  452. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoplayHandlers\\CancelAutoplay\\CLSID"),
  453. 0, MAXIMUM_ALLOWED, &hkey))
  454. {
  455. DWORD dwIndex = 0;
  456. WCHAR szCLSID[39] = TEXT("{");
  457. DWORD cchCLSID = ARRAYSIZE(szCLSID) - 1;
  458. while ((S_FALSE != hrRet) &&
  459. (ERROR_SUCCESS == RegEnumValue(hkey, dwIndex, &(szCLSID[1]),
  460. &cchCLSID, 0, 0, 0, 0)))
  461. {
  462. CLSID clsid;
  463. szCLSID[37] = TEXT('}');
  464. szCLSID[38] = 0;
  465. hr = CLSIDFromString(szCLSID, &clsid);
  466. if (SUCCEEDED(hr))
  467. {
  468. IMoniker* pmoniker;
  469. // Create the moniker that we'll put in the ROT
  470. hr = CreateClassMoniker(clsid, &pmoniker);
  471. if (SUCCEEDED(hr))
  472. {
  473. IUnknown* punk;
  474. hr = prot->GetObject(pmoniker, &punk);
  475. if (SUCCEEDED(hr) && (S_FALSE != hr))
  476. {
  477. IQueryCancelAutoPlay* pqca;
  478. hr = punk->QueryInterface(IID_PPV_ARG(IQueryCancelAutoPlay, &pqca));
  479. if (SUCCEEDED(hr))
  480. {
  481. hrRet = pqca->AllowAutoPlay(pqro->szMountPoint, pqro->dwContentType,
  482. pqro->szLabel, pqro->dwSerialNumber);
  483. pqca->Release();
  484. }
  485. punk->Release();
  486. }
  487. pmoniker->Release();
  488. }
  489. }
  490. ++dwIndex;
  491. cchCLSID = ARRAYSIZE(szCLSID) - 1;
  492. }
  493. RegCloseKey(hkey);
  494. }
  495. }
  496. pbindctx->Release();
  497. }
  498. if (S_FALSE != hrRet)
  499. {
  500. // This case is to support WMP and CD burning. We did not get to replace
  501. // their cancel logic before shipping.
  502. hr = SHCreateQueryCancelAutoPlayMoniker(&pmoniker);
  503. if (SUCCEEDED(hr))
  504. {
  505. IUnknown* punk;
  506. hr = prot->GetObject(pmoniker, &punk);
  507. if (SUCCEEDED(hr) && (S_FALSE != hr))
  508. {
  509. IQueryCancelAutoPlay* pqca;
  510. hr = punk->QueryInterface(IID_PPV_ARG(IQueryCancelAutoPlay, &pqca));
  511. if (SUCCEEDED(hr))
  512. {
  513. hrRet = pqca->AllowAutoPlay(pqro->szMountPoint, pqro->dwContentType,
  514. pqro->szLabel, pqro->dwSerialNumber);
  515. pqca->Release();
  516. }
  517. punk->Release();
  518. }
  519. pmoniker->Release();
  520. }
  521. }
  522. prot->Release();
  523. }
  524. CoUninitialize();
  525. }
  526. LocalFree((HLOCAL)pqro);
  527. return (DWORD)hrRet;
  528. }
  529. // static
  530. HRESULT CMountPoint::_QueryRunningObject(CMountPoint* pmtpt, DWORD dwAutorunContentType, BOOL* pfAllow)
  531. {
  532. *pfAllow = TRUE;
  533. QUERRYRUNNINGOBJECTSTRUCT *pqro;
  534. HRESULT hr = SHLocalAlloc(sizeof(*pqro), &pqro);
  535. if (SUCCEEDED(hr))
  536. {
  537. WCHAR szLabel[MAX_LABEL];
  538. if (!(ARCONTENT_BLANKCD & dwAutorunContentType) &&
  539. !(ARCONTENT_BLANKDVD & dwAutorunContentType))
  540. {
  541. if (pmtpt->_GetGVILabel(szLabel, ARRAYSIZE(szLabel)))
  542. {
  543. StringCchCopy(pqro->szLabel, ARRAYSIZE(pqro->szLabel), szLabel);
  544. pmtpt->_GetSerialNumber(&(pqro->dwSerialNumber));
  545. }
  546. }
  547. hr = StringCchCopy(pqro->szMountPoint, ARRAYSIZE(pqro->szMountPoint), pmtpt->_GetName());
  548. if (SUCCEEDED(hr))
  549. {
  550. pqro->dwContentType = dwAutorunContentType;
  551. HANDLE hThread = CreateThread(NULL, 0, _QueryRunningObjectThreadProc,
  552. pqro, 0, NULL);
  553. if (hThread)
  554. {
  555. // thread now owns these guys, NULL them out to avoid dbl free
  556. pqro = NULL; // don't free this below
  557. hr = S_FALSE;
  558. // Wait 3 sec to see if wants to process it. If not, it's
  559. // fair play for us.
  560. DWORD dwWait = WaitForSingleObject(hThread, 3000);
  561. if (WAIT_OBJECT_0 == dwWait)
  562. {
  563. // Return within time and did not failed
  564. DWORD dwExitCode;
  565. if (GetExitCodeThread(hThread, &dwExitCode))
  566. {
  567. HRESULT hrHandlesEvent = (HRESULT)dwExitCode;
  568. // Will return S_FALSE if they do NOT allow AutoRun
  569. if (SUCCEEDED(hrHandlesEvent) && (S_FALSE == hrHandlesEvent))
  570. {
  571. *pfAllow = FALSE;
  572. }
  573. hr = S_OK;
  574. }
  575. }
  576. CloseHandle(hThread);
  577. }
  578. else
  579. {
  580. hr = E_OUTOFMEMORY;
  581. }
  582. }
  583. LocalFree((HLOCAL)pqro); // may be NULL
  584. }
  585. return hr;
  586. }
  587. CAutoPlayParams::CAutoPlayParams(LPCWSTR pszDrive, CMountPoint* pMtPt, DWORD dwAutorunFlags)
  588. : _pszDrive(pszDrive),
  589. _pmtpt(pMtPt),
  590. _dwAutorunFlags(dwAutorunFlags),
  591. _state(APS_RESET),
  592. _pdo(NULL),
  593. _fCheckAlwaysDoThisCheckBox(FALSE)
  594. {
  595. _dwDriveType = pMtPt->_GetMTPTDriveType();
  596. _dwContentType = pMtPt->_GetMTPTContentType();
  597. if (DT_ANYLOCALDRIVES & _dwDriveType)
  598. _pmtptl = (CMtPtLocal*)pMtPt;
  599. else
  600. _pmtptl = NULL;
  601. // maybe assert on these?
  602. }
  603. BOOL CAutoPlayParams::_ShouldSniffDrive(BOOL fCheckHandlerDefaults)
  604. {
  605. BOOL fSniff = FALSE;
  606. if (_pmtptl)
  607. {
  608. if (CT_AUTORUNINF & _dwContentType)
  609. {
  610. if (_pmtptl->_CanUseVolume())
  611. {
  612. if (_pmtptl->_pvol->dwMediaCap & HWDMC_HASUSEAUTOPLAY)
  613. {
  614. fSniff = TRUE;
  615. }
  616. }
  617. }
  618. else
  619. {
  620. fSniff = TRUE;
  621. }
  622. if (fSniff)
  623. {
  624. fSniff = FALSE;
  625. if (!((CT_CDAUDIO | CT_DVDMOVIE) & _dwContentType))
  626. {
  627. if (_pmtptl->_CanUseVolume())
  628. {
  629. if (!(HWDVF_STATE_HASAUTOPLAYHANDLER & _pmtptl->_pvol->dwVolumeFlags) &&
  630. !(HWDVF_STATE_DONOTSNIFFCONTENT & _pmtptl->_pvol->dwVolumeFlags))
  631. {
  632. if (AUTORUNFLAG_MENUINVOKED & _dwAutorunFlags)
  633. {
  634. fSniff = TRUE;
  635. }
  636. else if (DT_FIXEDDISK & _dwDriveType)
  637. {
  638. if (HWDDC_REMOVABLEDEVICE & _pmtptl->_pvol->dwDriveCapability)
  639. {
  640. fSniff = TRUE;
  641. }
  642. }
  643. else
  644. {
  645. if (AUTORUNFLAG_MEDIAARRIVAL & _dwAutorunFlags)
  646. {
  647. fSniff = TRUE;
  648. }
  649. else
  650. {
  651. if (AUTORUNFLAG_MTPTARRIVAL & _dwAutorunFlags)
  652. {
  653. if (HWDDC_REMOVABLEDEVICE & _pmtptl->_pvol->dwDriveCapability)
  654. {
  655. fSniff = TRUE;
  656. }
  657. }
  658. }
  659. }
  660. }
  661. }
  662. }
  663. }
  664. }
  665. if (fSniff && fCheckHandlerDefaults)
  666. {
  667. // Let's make sure the user did not pick "Take no action" for all Autoplay
  668. // content types, it would be useless to sniff.
  669. BOOL fAllTakeNoAction = TRUE;
  670. DWORD rgdwContentType[] =
  671. {
  672. CT_AUTOPLAYMUSIC,
  673. CT_AUTOPLAYPIX,
  674. CT_AUTOPLAYMOVIE,
  675. CT_AUTOPLAYMUSIC | CT_AUTOPLAYPIX | CT_AUTOPLAYMOVIE, // Mix content
  676. };
  677. for (DWORD dw = 0; fAllTakeNoAction && (dw < ARRAYSIZE(rgdwContentType)); ++dw)
  678. {
  679. WCHAR szContentTypeHandler[MAX_CONTENTTYPEHANDLER];
  680. DWORD dwMtPtContentType = rgdwContentType[dw];
  681. HRESULT hr = _GetContentTypeHandler(dwMtPtContentType, szContentTypeHandler, ARRAYSIZE(szContentTypeHandler));
  682. if (SUCCEEDED(hr))
  683. {
  684. IAutoplayHandler* piah;
  685. hr = _GetAutoplayHandler(Drive(), TEXT("ContentArrival"), szContentTypeHandler, &piah);
  686. if (SUCCEEDED(hr))
  687. {
  688. LPWSTR pszHandlerDefault;
  689. hr = piah->GetDefaultHandler(&pszHandlerDefault);
  690. if (SUCCEEDED(hr))
  691. {
  692. if (HANDLERDEFAULT_MORERECENTHANDLERSINSTALLED &
  693. HANDLERDEFAULT_GETFLAGS(hr))
  694. {
  695. fAllTakeNoAction = FALSE;
  696. }
  697. else
  698. {
  699. if (lstrcmpi(pszHandlerDefault, TEXT("MSTakeNoAction")))
  700. {
  701. fAllTakeNoAction = FALSE;
  702. }
  703. }
  704. CoTaskMemFree(pszHandlerDefault);
  705. }
  706. piah->Release();
  707. }
  708. }
  709. }
  710. if (fAllTakeNoAction)
  711. {
  712. fSniff = FALSE;
  713. }
  714. }
  715. return fSniff;
  716. }
  717. DWORD CAutoPlayParams::ContentType()
  718. {
  719. return _dwContentType;
  720. }
  721. HRESULT CAutoPlayParams::_InitObjects(IShellFolder **ppsf)
  722. {
  723. HRESULT hr;
  724. if (!_pdo || ppsf)
  725. {
  726. LPITEMIDLIST pidlFolder;
  727. hr = SHParseDisplayName(_pszDrive, NULL, &pidlFolder, 0, NULL);
  728. if (SUCCEEDED(hr))
  729. {
  730. hr = SHGetUIObjectOf(pidlFolder, NULL, IID_PPV_ARG(IDataObject, &_pdo));
  731. ILFree(pidlFolder);
  732. }
  733. }
  734. else
  735. {
  736. hr = S_OK;
  737. }
  738. if (SUCCEEDED(hr) && ppsf)
  739. {
  740. // we need to avoid hitting the burn folder
  741. // so we skip junctions for the sniff
  742. IBindCtx * pbc;
  743. hr = SHCreateSkipBindCtx(NULL, &pbc);
  744. if (SUCCEEDED(hr))
  745. {
  746. LPITEMIDLIST pidlFolder;
  747. hr = SHParseDisplayName(_pszDrive, pbc, &pidlFolder, 0, NULL);
  748. if (SUCCEEDED(hr))
  749. {
  750. hr = SHBindToObjectEx(NULL, pidlFolder, pbc, IID_PPV_ARG(IShellFolder, ppsf));
  751. ILFree(pidlFolder);
  752. }
  753. pbc->Release();
  754. }
  755. }
  756. return hr;
  757. }
  758. HRESULT CAutoPlayParams::_AddWalkToDataObject(INamespaceWalk* pnsw)
  759. {
  760. UINT cidl;
  761. LPITEMIDLIST *apidl;
  762. HRESULT hr = pnsw->GetIDArrayResult(&cidl, &apidl);
  763. if (SUCCEEDED(hr))
  764. {
  765. // we need to add this back in
  766. if (cidl)
  767. {
  768. // ragged array
  769. HIDA hida = HIDA_Create(&c_idlDesktop, cidl, (LPCITEMIDLIST *)apidl);
  770. if (hida)
  771. {
  772. IDLData_InitializeClipboardFormats(); // init our registerd formats
  773. // should we free hida on FAILED?
  774. DataObj_SetGlobal(_pdo, g_cfAutoPlayHIDA, hida);
  775. }
  776. }
  777. FreeIDListArray(apidl, cidl);
  778. }
  779. return hr;
  780. }
  781. HRESULT CAutoPlayParams::_Sniff(DWORD *pdwFound)
  782. {
  783. // we found nothing
  784. HRESULT hr = S_FALSE;
  785. *pdwFound = 0;
  786. if (_pmtptl->_CanUseVolume())
  787. {
  788. // setup the IDataObject and IShellFolder for the walk
  789. IShellFolder *psf;
  790. HRESULT hr = _InitObjects(&psf);
  791. if (SUCCEEDED(hr))
  792. {
  793. INamespaceWalk* pnsw;
  794. hr = CoCreateInstance(CLSID_NamespaceWalker, NULL, CLSCTX_INPROC, IID_PPV_ARG(INamespaceWalk, &pnsw));
  795. if (SUCCEEDED(hr))
  796. {
  797. CSniffDrive sniff;
  798. hr = sniff.RegisterForNotifs(_pmtptl->_pvol->pszDeviceIDVolume);
  799. if (SUCCEEDED(hr))
  800. {
  801. // We don't care about the return value. WE don't want to stop Autorun for as much.
  802. // If sniffing fail we go on with what we have.
  803. if (SUCCEEDED(pnsw->Walk(psf, NSWF_IGNORE_AUTOPLAY_HIDA | NSWF_DONT_TRAVERSE_LINKS | NSWF_SHOW_PROGRESS, 4, &sniff)))
  804. {
  805. // we keep everything we found
  806. _AddWalkToDataObject(pnsw);
  807. }
  808. sniff.UnregisterForNotifs();
  809. *pdwFound = sniff.Found();
  810. }
  811. pnsw->Release();
  812. }
  813. psf->Release();
  814. }
  815. }
  816. return hr;
  817. }
  818. // BEGIN: Fcts for matrix below
  819. //
  820. BOOL CMountPoint::_acShiftKeyDown(HWND , CAutoPlayParams *)
  821. {
  822. return (GetAsyncKeyState(VK_SHIFT) < 0);
  823. }
  824. BOOL _IsDirectXExclusiveMode()
  825. {
  826. BOOL fRet = FALSE;
  827. // This code determines whether a DirectDraw 7 process (game) is running and
  828. // whether it's exclusively holding the video to the machine in full screen mode.
  829. // The code is probably to be considered untrusted and hence is wrapped in a
  830. // __try / __except block. It could AV and therefore bring down shell
  831. // with it. Not very good. If the code does raise an exception the release
  832. // call is skipped. Tough. Don't trust the release method either.
  833. IDirectDraw7 *pIDirectDraw7 = NULL;
  834. HRESULT hr = CoCreateInstance(CLSID_DirectDraw7, NULL, CLSCTX_INPROC_SERVER,
  835. IID_IDirectDraw7, (void**)&pIDirectDraw7);
  836. if (SUCCEEDED(hr))
  837. {
  838. ASSERT(pIDirectDraw7);
  839. __try
  840. {
  841. hr = IDirectDraw7_Initialize(pIDirectDraw7, NULL);
  842. if (DD_OK == hr)
  843. {
  844. fRet = (IDirectDraw7_TestCooperativeLevel(pIDirectDraw7) ==
  845. DDERR_EXCLUSIVEMODEALREADYSET);
  846. }
  847. IDirectDraw7_Release(pIDirectDraw7);
  848. }
  849. __except (EXCEPTION_EXECUTE_HANDLER)
  850. {
  851. }
  852. }
  853. return fRet;
  854. }
  855. // From a mail regarding the DirectX fct below:
  856. //
  857. // You can definitely count on the following:
  858. //
  859. // (1) If shadow cursors are on, there is definitely not an exclusive mode app running.
  860. // (2) If hot tracking is on, there is definitely not an exclusive mode app running.
  861. // (3) If message boxes for SEM_NOGPFAULTERRORBOX, SEM_FAILCRITICALERRORS, or
  862. // SEM_NOOPENFILEERRORBOX have not been disabled via SetErrorMode, then there
  863. // is definitely not an exclusive mode app running.
  864. //
  865. // Note: we cannot use (3) since this is per-process.
  866. BOOL CMountPoint::_acDirectXAppRunningFullScreen(HWND hwndForeground, CAutoPlayParams *)
  867. {
  868. BOOL fRet = FALSE;
  869. BOOL fSPI;
  870. if (SystemParametersInfo(SPI_GETCURSORSHADOW, 0, &fSPI, 0) && !fSPI)
  871. {
  872. if (SystemParametersInfo(SPI_GETHOTTRACKING, 0, &fSPI, 0) && !fSPI)
  873. {
  874. // There's a chance that a DirectX app is running full screen. Let's do the
  875. // expensive DirectX calls that will tell us for sure.
  876. fRet = _IsDirectXExclusiveMode();
  877. }
  878. }
  879. return fRet;
  880. }
  881. BOOL CMountPoint::_acCurrentDesktopIsActiveConsole(HWND , CAutoPlayParams *)
  882. {
  883. BOOL fRetValue = FALSE; // block auto-run/auto-play if we can't determine our state.
  884. if (0 == GetSystemMetrics(SM_REMOTESESSION))
  885. {
  886. //
  887. // We are not remoted. See if we are the active console session.
  888. //
  889. BOOL b;
  890. DWORD dwProcessSession;
  891. b = ProcessIdToSessionId(GetCurrentProcessId(), &dwProcessSession);
  892. if (b)
  893. {
  894. DWORD dwConsoleSession = WTSGetActiveConsoleSessionId( );
  895. if ( dwProcessSession == dwConsoleSession )
  896. {
  897. //
  898. // See if the screen saver is running.
  899. //
  900. BOOL b;
  901. BOOL fScreenSaver;
  902. b = SystemParametersInfo( SPI_GETSCREENSAVERRUNNING, 0, &fScreenSaver, 0 );
  903. if (b)
  904. {
  905. if (!fScreenSaver)
  906. {
  907. //
  908. // We made it here, we must be the active console session without a
  909. // screen saver.
  910. //
  911. HDESK hDesk = OpenInputDesktop( 0, FALSE, DESKTOP_CREATEWINDOW );
  912. if ( NULL != hDesk )
  913. {
  914. //
  915. // We have access to the current desktop which should indicate that
  916. // WinLogon isn't.
  917. //
  918. CloseDesktop( hDesk );
  919. fRetValue = TRUE;
  920. }
  921. // else "WinLogon" has the "desktop"... don't allow auto-run/auto-play.
  922. }
  923. // else a screen saver is running... don't allow auto-run/auto-play.
  924. }
  925. // else we are in an undeterminate state... don't allow auto-run/auto-play.
  926. }
  927. // else we aren't the console... don't allow auto-run/auto-play
  928. }
  929. // else we are in an undeterminate state... don't allow auto-run/auto-play.
  930. }
  931. // else we are remoted... don't allow auto-run/auto-play.
  932. return fRetValue;
  933. }
  934. BOOL CMountPoint::_acDriveIsMountedOnDriveLetter(HWND , CAutoPlayParams *papp)
  935. {
  936. return _IsDriveLetter(papp->Drive());
  937. }
  938. BOOL CMountPoint::_acDriveIsRestricted(HWND , CAutoPlayParams *papp)
  939. {
  940. BOOL fIsRestricted = (SHRestricted(REST_NODRIVES) & (1 << DRIVEID(papp->Drive())));
  941. if (!fIsRestricted)
  942. {
  943. fIsRestricted = !(papp->MountPoint()->_IsAutoRunDrive());
  944. }
  945. return fIsRestricted;
  946. }
  947. BOOL CMountPoint::_acHasAutorunCommand(HWND , CAutoPlayParams *papp)
  948. {
  949. BOOL fRet = FALSE;
  950. if ((papp->IsContentTypePresent(CT_AUTORUNINF)) &&
  951. (DT_ANYLOCALDRIVES & papp->DriveType()))
  952. {
  953. CMtPtLocal* pmtptl = (CMtPtLocal*)papp->MountPoint();
  954. if (pmtptl->_CanUseVolume())
  955. {
  956. if (pmtptl->_pvol->dwMediaCap & HWDMC_HASAUTORUNCOMMAND)
  957. {
  958. fRet = TRUE;
  959. }
  960. }
  961. else
  962. {
  963. fRet = papp->MountPoint()->_IsAutorun();
  964. }
  965. }
  966. else
  967. {
  968. fRet = papp->IsContentTypePresent(CT_AUTORUNINF);
  969. }
  970. return fRet;
  971. }
  972. BOOL CMountPoint::_acHasUseAutoPLAY(HWND , CAutoPlayParams *papp)
  973. {
  974. BOOL fRet = FALSE;
  975. if (papp->IsContentTypePresent(CT_AUTORUNINF) &&
  976. (DT_ANYLOCALDRIVES & papp->DriveType()))
  977. {
  978. CMtPtLocal* pmtptl = (CMtPtLocal*)papp->MountPoint();
  979. if (pmtptl->_CanUseVolume())
  980. {
  981. if (pmtptl->_pvol->dwMediaCap & HWDMC_HASUSEAUTOPLAY)
  982. {
  983. fRet = TRUE;
  984. }
  985. }
  986. else
  987. {
  988. // If we're here, most likely the ShellService is not running, so we won't be able to
  989. // Autoplay anyway.
  990. fRet = FALSE;
  991. }
  992. }
  993. else
  994. {
  995. // not supported for remote drives
  996. }
  997. return fRet;
  998. }
  999. BOOL CMountPoint::_acForegroundAppAllowsAutorun(HWND hwndForeground, CAutoPlayParams *papp)
  1000. {
  1001. return _AppAllowsAutoRun(hwndForeground, papp->MountPoint());
  1002. }
  1003. static const TWODWORDS allcontentsVSarcontenttypemappings[] =
  1004. {
  1005. { CT_AUTORUNINF , ARCONTENT_AUTORUNINF },
  1006. { CT_CDAUDIO , ARCONTENT_AUDIOCD },
  1007. { CT_DVDMOVIE , ARCONTENT_DVDMOVIE },
  1008. { CT_UNKNOWNCONTENT , ARCONTENT_UNKNOWNCONTENT },
  1009. { CT_BLANKCDR , ARCONTENT_BLANKCD },
  1010. { CT_BLANKCDRW , ARCONTENT_BLANKCD },
  1011. { CT_BLANKDVDR , ARCONTENT_BLANKDVD },
  1012. { CT_BLANKDVDRW , ARCONTENT_BLANKDVD },
  1013. { CT_AUTOPLAYMUSIC , ARCONTENT_AUTOPLAYMUSIC },
  1014. { CT_AUTOPLAYPIX , ARCONTENT_AUTOPLAYPIX },
  1015. { CT_AUTOPLAYMOVIE , ARCONTENT_AUTOPLAYVIDEO },
  1016. };
  1017. BOOL CMountPoint::_acQueryCancelAutoplayAllowsAutorun(HWND , CAutoPlayParams *papp)
  1018. {
  1019. BOOL fAllow = TRUE;
  1020. DWORD dwAutorunContentType = _DoDWORDMapping(papp->ContentType(),
  1021. allcontentsVSarcontenttypemappings, ARRAYSIZE(allcontentsVSarcontenttypemappings),
  1022. TRUE);
  1023. _QueryRunningObject(papp->MountPoint(), dwAutorunContentType, &fAllow);
  1024. return fAllow;
  1025. }
  1026. BOOL CMountPoint::_acUserHasSelectedApplication(HWND hwndForeground, CAutoPlayParams *papp)
  1027. {
  1028. BOOL fRet = FALSE;
  1029. WCHAR szContentTypeHandler[MAX_CONTENTTYPEHANDLER];
  1030. DWORD dwMtPtContentType = papp->ContentType() & ~CT_UNKNOWNCONTENT;
  1031. HRESULT hr = _GetContentTypeHandler(dwMtPtContentType, szContentTypeHandler, ARRAYSIZE(szContentTypeHandler));
  1032. if (SUCCEEDED(hr))
  1033. {
  1034. IAutoplayHandler* piah;
  1035. hr = _GetAutoplayHandler(papp->Drive(), TEXT("ContentArrival"), szContentTypeHandler, &piah);
  1036. if (SUCCEEDED(hr))
  1037. {
  1038. LPWSTR pszHandlerDefault;
  1039. hr = piah->GetDefaultHandler(&pszHandlerDefault);
  1040. if (SUCCEEDED(hr))
  1041. {
  1042. if (HANDLERDEFAULT_MORERECENTHANDLERSINSTALLED &
  1043. HANDLERDEFAULT_GETFLAGS(hr))
  1044. {
  1045. fRet = FALSE;
  1046. }
  1047. else
  1048. {
  1049. if (HANDLERDEFAULT_USERCHOSENDEFAULT &
  1050. HANDLERDEFAULT_GETFLAGS(hr))
  1051. {
  1052. fRet = lstrcmpi(pszHandlerDefault, TEXT("MSPromptEachTime"));
  1053. }
  1054. else
  1055. {
  1056. fRet = FALSE;
  1057. }
  1058. }
  1059. if (!fRet)
  1060. {
  1061. if (((HANDLERDEFAULT_USERCHOSENDEFAULT &
  1062. HANDLERDEFAULT_GETFLAGS(hr)) ||
  1063. (HANDLERDEFAULT_EVENTHANDLERDEFAULT &
  1064. HANDLERDEFAULT_GETFLAGS(hr))) &&
  1065. !(HANDLERDEFAULT_DEFAULTSAREDIFFERENT &
  1066. HANDLERDEFAULT_GETFLAGS(hr)))
  1067. {
  1068. papp->_fCheckAlwaysDoThisCheckBox = TRUE;
  1069. }
  1070. }
  1071. CoTaskMemFree(pszHandlerDefault);
  1072. }
  1073. piah->Release();
  1074. }
  1075. }
  1076. return fRet;
  1077. }
  1078. BOOL CMountPoint::_acShellIsForegroundApp(HWND hwndForeground, CAutoPlayParams *papp)
  1079. {
  1080. BOOL fRet = FALSE;
  1081. WCHAR szModule[MAX_PATH];
  1082. if (GetWindowModuleFileName(hwndForeground, szModule, ARRAYSIZE(szModule)))
  1083. {
  1084. if (!lstrcmpi(PathFindFileName(szModule), TEXT("explorer.exe")))
  1085. {
  1086. fRet = TRUE;
  1087. }
  1088. }
  1089. return fRet;
  1090. }
  1091. BOOL CMountPoint::_acOSIsServer(HWND , CAutoPlayParams *papp)
  1092. {
  1093. return IsOS(OS_ANYSERVER);
  1094. }
  1095. BOOL CMountPoint::_acIsDockedLaptop(HWND hwndForeground, CAutoPlayParams *papp)
  1096. {
  1097. return (GMID_DOCKED & SHGetMachineInfo(GMI_DOCKSTATE));
  1098. }
  1099. BOOL CMountPoint::_acDriveIsFormatted(HWND hwndForeground, CAutoPlayParams *papp)
  1100. {
  1101. return papp->MountPoint()->IsFormatted();
  1102. }
  1103. BOOL CMountPoint::_acShellExecuteDriveAutorunINF(HWND hwndForeground, CAutoPlayParams *papp)
  1104. {
  1105. SHELLEXECUTEINFO ei = {
  1106. sizeof(ei), // size
  1107. SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_NO_UI, // flags
  1108. NULL,
  1109. NULL, // verb
  1110. papp->Drive(), // file
  1111. papp->Drive(), // params
  1112. papp->Drive(), // directory
  1113. SW_NORMAL, // show.
  1114. NULL, // hinstance
  1115. NULL, // IDLIST
  1116. NULL, // class name
  1117. NULL, // class key
  1118. 0, // hot key
  1119. NULL, // icon
  1120. NULL, // hProcess
  1121. };
  1122. return ShellExecuteEx(&ei);
  1123. }
  1124. HRESULT _InvokeAutoRunProgid(HKEY hkProgid, LPCWSTR pszVerb, IDataObject *pdo)
  1125. {
  1126. IShellExtInit *psei;
  1127. HRESULT hr = CoCreateInstance(CLSID_ShellFileDefExt, NULL, CLSCTX_INPROC, IID_PPV_ARG(IShellExtInit, &psei));
  1128. if (SUCCEEDED(hr))
  1129. {
  1130. hr = psei->Initialize(NULL, pdo, hkProgid);
  1131. if (SUCCEEDED(hr))
  1132. {
  1133. IContextMenu *pcm;
  1134. hr = psei->QueryInterface(IID_PPV_ARG(IContextMenu, &pcm));
  1135. if (SUCCEEDED(hr))
  1136. {
  1137. CHAR szVerb[64];
  1138. // maybe hwnd
  1139. // maybe punkSite
  1140. // maybe ICI flags
  1141. SHUnicodeToAnsi(pszVerb, szVerb, ARRAYSIZE(szVerb));
  1142. hr = SHInvokeCommandOnContextMenu(NULL, NULL, pcm, 0, szVerb);
  1143. pcm->Release();
  1144. }
  1145. }
  1146. psei->Release();
  1147. }
  1148. return hr;
  1149. }
  1150. HRESULT _GetProgidAndVerb(DWORD dwContentType, PCWSTR pszHandler, PWSTR pszInvokeProgID,
  1151. DWORD cchInvokeProgID, PWSTR pszInvokeVerb, DWORD cchInvokeVerb)
  1152. {
  1153. HRESULT hr;
  1154. if (0 == StrCmpI(pszHandler, TEXT("AutoplayLegacyHandler")) && (dwContentType & (CT_CDAUDIO | CT_DVDMOVIE)))
  1155. {
  1156. HKEY hkey;
  1157. BOOL fGotDefault = FALSE;
  1158. if (dwContentType & CT_CDAUDIO)
  1159. {
  1160. hr = StringCchCopy(pszInvokeProgID, cchInvokeProgID, TEXT("AudioCD"));
  1161. }
  1162. else
  1163. {
  1164. ASSERT(dwContentType & CT_DVDMOVIE);
  1165. hr = StringCchCopy(pszInvokeProgID, cchInvokeProgID, TEXT("DVD"));
  1166. }
  1167. if (SUCCEEDED(hr))
  1168. {
  1169. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, pszInvokeProgID, 0, MAXIMUM_ALLOWED,
  1170. &hkey))
  1171. {
  1172. HKEY hkey2;
  1173. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, TEXT("shell"), 0, MAXIMUM_ALLOWED,
  1174. &hkey2))
  1175. {
  1176. DWORD cbInvokeVerb = cchInvokeVerb * sizeof(WCHAR);
  1177. if (ERROR_SUCCESS == RegQueryValueEx(hkey2, NULL, NULL, NULL, (PBYTE)pszInvokeVerb,
  1178. &cbInvokeVerb))
  1179. {
  1180. if (cbInvokeVerb && *pszInvokeVerb)
  1181. {
  1182. if (cbInvokeVerb != (cchInvokeVerb * sizeof(WCHAR)))
  1183. {
  1184. fGotDefault = TRUE;
  1185. }
  1186. }
  1187. }
  1188. RegCloseKey(hkey2);
  1189. }
  1190. RegCloseKey(hkey);
  1191. }
  1192. if (!fGotDefault)
  1193. {
  1194. hr = StringCchCopy(pszInvokeVerb, cchInvokeVerb, TEXT("play"));
  1195. }
  1196. }
  1197. }
  1198. else
  1199. {
  1200. hr = _GetHandlerInvokeProgIDAndVerb(pszHandler, pszInvokeProgID,
  1201. cchInvokeProgID, pszInvokeVerb, cchInvokeVerb);
  1202. }
  1203. return hr;
  1204. }
  1205. BOOL CMountPoint::_ExecuteHelper(LPCWSTR pszHandler, LPCWSTR pszContentTypeHandler,
  1206. CAutoPlayParams *papp, DWORD dwMtPtContentType)
  1207. {
  1208. HRESULT hr;
  1209. if (lstrcmpi(pszHandler, TEXT("MSTakeNoAction")))
  1210. {
  1211. WCHAR szInvokeProgID[260];
  1212. WCHAR szInvokeVerb[CCH_KEYMAX];
  1213. hr = _GetProgidAndVerb(dwMtPtContentType, pszHandler, szInvokeProgID,
  1214. ARRAYSIZE(szInvokeProgID), szInvokeVerb, ARRAYSIZE(szInvokeVerb));
  1215. if (SUCCEEDED(hr))
  1216. {
  1217. HKEY hkey;
  1218. if (dwMtPtContentType & (CT_CDAUDIO | CT_DVDMOVIE))
  1219. {
  1220. hr = papp->MountPoint()->_CopyInvokeVerbKey(szInvokeProgID, szInvokeVerb);
  1221. if (SUCCEEDED(hr))
  1222. {
  1223. hkey = papp->MountPoint()->RSDuplicateRootKey();
  1224. if (hkey)
  1225. {
  1226. papp->MountPoint()->RSSetTextValue(TEXT("shell"), NULL, szInvokeVerb,
  1227. REG_OPTION_NON_VOLATILE);
  1228. }
  1229. else
  1230. {
  1231. hr = E_FAIL;
  1232. }
  1233. }
  1234. }
  1235. else
  1236. {
  1237. hr = ResultFromWin32(RegOpenKeyExW(HKEY_CLASSES_ROOT, szInvokeProgID, 0, MAXIMUM_ALLOWED, &hkey));
  1238. }
  1239. if (SUCCEEDED(hr))
  1240. {
  1241. IDataObject* pdo;
  1242. hr = papp->DataObject(&pdo);
  1243. if (SUCCEEDED(hr))
  1244. {
  1245. hr = _InvokeAutoRunProgid(hkey, szInvokeVerb, pdo);
  1246. pdo->Release();
  1247. }
  1248. RegCloseKey(hkey);
  1249. }
  1250. }
  1251. }
  1252. else
  1253. {
  1254. hr = S_FALSE;
  1255. }
  1256. return SUCCEEDED(hr);
  1257. }
  1258. BOOL CMountPoint::_acExecuteAutoplayDefault(HWND hwndForeground, CAutoPlayParams *papp)
  1259. {
  1260. BOOL fRet = FALSE;
  1261. if (DT_ANYLOCALDRIVES & papp->DriveType())
  1262. {
  1263. WCHAR szContentTypeHandler[MAX_CONTENTTYPEHANDLER];
  1264. DWORD dwMtPtContentType = papp->ContentType() & ~CT_UNKNOWNCONTENT;
  1265. HRESULT hr = _GetContentTypeHandler(dwMtPtContentType, szContentTypeHandler, ARRAYSIZE(szContentTypeHandler));
  1266. if (SUCCEEDED(hr))
  1267. {
  1268. IAutoplayHandler* piah;
  1269. hr = _GetAutoplayHandler(papp->Drive(), TEXT("ContentArrival"), szContentTypeHandler, &piah);
  1270. if (SUCCEEDED(hr))
  1271. {
  1272. LPWSTR pszHandlerDefault;
  1273. hr = piah->GetDefaultHandler(&pszHandlerDefault);
  1274. if (SUCCEEDED(hr))
  1275. {
  1276. // No need to check for (S_HANDLERS_MORE_RECENT_THAN_USER_SELECTION == hr) here
  1277. // It should have been caught by _acUserHasSelectedApplication
  1278. fRet = _ExecuteHelper(pszHandlerDefault, szContentTypeHandler, papp, dwMtPtContentType);
  1279. }
  1280. CoTaskMemFree(pszHandlerDefault);
  1281. }
  1282. piah->Release();
  1283. }
  1284. }
  1285. return fRet;
  1286. }
  1287. BOOL CMountPoint::_acWasjustDocked(HWND hwndForeground, CAutoPlayParams *papp)
  1288. {
  1289. BOOL fRet = FALSE;
  1290. if (DT_ANYLOCALDRIVES & papp->DriveType())
  1291. {
  1292. CMtPtLocal* pmtptl = (CMtPtLocal*)papp->MountPoint();
  1293. if (pmtptl->_CanUseVolume())
  1294. {
  1295. if (pmtptl->_pvol->dwVolumeFlags & HWDVF_STATE_JUSTDOCKED)
  1296. {
  1297. fRet = TRUE;
  1298. }
  1299. }
  1300. }
  1301. return fRet;
  1302. }
  1303. CRITICAL_SECTION g_csAutoplayPrompt = {0};
  1304. HDPA g_hdpaAutoplayPrompt = NULL;
  1305. BOOL CMountPoint::_acPromptUser(HWND hwndForeground, CAutoPlayParams *papp)
  1306. {
  1307. BOOL fRet = FALSE;
  1308. BOOL fShowDlg = TRUE;
  1309. if (papp->Drive())
  1310. {
  1311. fShowDlg = _AddAutoplayPrompt(papp->Drive());
  1312. }
  1313. if (fShowDlg)
  1314. {
  1315. CBaseContentDlg* pdlg;
  1316. papp->ForceSniff();
  1317. DWORD dwMtPtContentType = papp->ContentType() & ~CT_UNKNOWNCONTENT;
  1318. if (dwMtPtContentType)
  1319. {
  1320. if (_acIsMixedContent(hwndForeground, papp))
  1321. {
  1322. pdlg = new CMixedContentDlg();
  1323. dwMtPtContentType &= CT_ANYAUTOPLAYCONTENT;
  1324. if (pdlg)
  1325. {
  1326. pdlg->_iResource = DLG_APMIXEDCONTENT;
  1327. }
  1328. }
  1329. else
  1330. {
  1331. pdlg = new CHWContentPromptDlg();
  1332. if (pdlg)
  1333. {
  1334. pdlg->_iResource = DLG_APPROMPTUSER;
  1335. }
  1336. }
  1337. }
  1338. if (pdlg)
  1339. {
  1340. // Better be a local drive
  1341. if (DT_ANYLOCALDRIVES & papp->DriveType())
  1342. {
  1343. CMtPtLocal* pmtptl = (CMtPtLocal*)papp->MountPoint();
  1344. if (pmtptl->_CanUseVolume())
  1345. {
  1346. HRESULT hr = pdlg->Init(pmtptl->_pvol->pszDeviceIDVolume, papp->Drive(), dwMtPtContentType,
  1347. papp->_fCheckAlwaysDoThisCheckBox);
  1348. pdlg->_hinst = g_hinst;
  1349. pdlg->_hwndParent = NULL;
  1350. if (SUCCEEDED(hr))
  1351. {
  1352. INT_PTR iRet = pdlg->DoModal(pdlg->_hinst, MAKEINTRESOURCE(pdlg->_iResource),
  1353. pdlg->_hwndParent);
  1354. if (IDOK == iRet)
  1355. {
  1356. fRet = _ExecuteHelper(pdlg->_szHandler, pdlg->_szContentTypeHandler,
  1357. papp, dwMtPtContentType);
  1358. }
  1359. }
  1360. }
  1361. }
  1362. pdlg->Release();
  1363. }
  1364. if (papp->Drive())
  1365. {
  1366. _RemoveFromAutoplayPromptHDPA(papp->Drive());
  1367. }
  1368. }
  1369. return fRet;
  1370. }
  1371. BOOL CMountPoint::_acIsMixedContent(HWND hwndForeground, CAutoPlayParams *papp)
  1372. {
  1373. BOOL fRet;
  1374. if (papp->IsContentTypePresent(CT_ANYAUTOPLAYCONTENT))
  1375. {
  1376. fRet = IsMixedContent(papp->ContentType());
  1377. }
  1378. else
  1379. {
  1380. fRet = FALSE;
  1381. }
  1382. return fRet;
  1383. }
  1384. BOOL CMountPoint::_acAlwaysReturnsTRUE(HWND hwndForeground, CAutoPlayParams *papp)
  1385. {
  1386. return TRUE;
  1387. }
  1388. BOOL CMountPoint::_acShouldSniff(HWND hwndForeground, CAutoPlayParams *papp)
  1389. {
  1390. BOOL fRet = TRUE;
  1391. CMtPtLocal* pmtptl = papp->MountPointLocal();
  1392. if (pmtptl)
  1393. {
  1394. if (pmtptl->_CanUseVolume())
  1395. {
  1396. fRet = !(HWDVF_STATE_DONOTSNIFFCONTENT & pmtptl->_pvol->dwVolumeFlags);
  1397. }
  1398. }
  1399. return fRet;
  1400. }
  1401. BOOL CMountPoint::_acAddAutoplayVerb(HWND hwndForeground, CAutoPlayParams *papp)
  1402. {
  1403. CMtPtLocal* pmtptl = papp->MountPointLocal();
  1404. if (pmtptl)
  1405. {
  1406. if (pmtptl->_CanUseVolume())
  1407. {
  1408. // We don't care about the return value
  1409. pmtptl->_AddAutoplayVerb();
  1410. }
  1411. }
  1412. return TRUE;
  1413. }
  1414. //
  1415. // END: Fcts for matrix below
  1416. #define SKIPDEPENDENTS_ONFALSE 0x00000001 // Skips dependents
  1417. #define SKIPDEPENDENTS_ONTRUE 0x00000002 // Skips dependents
  1418. #define CANCEL_AUTOPLAY_ONFALSE 0x00000004
  1419. #define CANCEL_AUTOPLAY_ONTRUE 0x00000008
  1420. #define NOTAPPLICABLE_ONANY 0x00000010
  1421. #define LEVEL_EXECUTE 0x10000000
  1422. #define LEVEL_SKIP 0x20000000
  1423. #define LEVEL_SPECIALMASK 0x30000000
  1424. #define LEVEL_REALLEVELMASK 0x0FFFFFFF
  1425. typedef BOOL (AUTORUNFCT)(HWND hwndForeground, CAutoPlayParams *papp);
  1426. // fct is called with pszDrive, papp->MountPoint(), hwndForeground, drive type and content type
  1427. struct AUTORUNCONDITION
  1428. {
  1429. DWORD dwNestingLevel;
  1430. DWORD dwMtPtDriveType;
  1431. DWORD dwMtPtContentType;
  1432. DWORD dwReturnValueHandling;
  1433. AUTORUNFCT* fct;
  1434. #ifdef DEBUG
  1435. LPCWSTR pszDebug;
  1436. #endif
  1437. };
  1438. // For this table to be more readable, add the content of \\stephstm\public\usertype.dat to
  1439. // %ProgramFiles%\Microsoft Visual Studio\Common\MSDev98\Bin\usertype.dat
  1440. // then restart MSDev
  1441. // AR_ENTRY -> AUTORUN_ENTRY
  1442. #ifdef DEBUG
  1443. #define AR_ENTRY(a, b, c, d, e) { (a), (b), (c), (d), CMountPoint::e, TEXT(#a) TEXT(":") TEXT(#b) TEXT(":") TEXT(#c) TEXT(":") TEXT(#d) TEXT(":") TEXT(#e) }
  1444. #else
  1445. #define AR_ENTRY(a, b, c, d, e) { (a), (b), (c), (d), CMountPoint::e }
  1446. #endif
  1447. // DT_* -> DriveType
  1448. // CT_* -> ContentType
  1449. static const AUTORUNCONDITION _rgAutorun[] =
  1450. {
  1451. // We don't autorun if the drive is not mounted on a drive letter
  1452. AR_ENTRY(0, DT_ANYTYPE, CT_ANYCONTENT, CANCEL_AUTOPLAY_ONFALSE, _acDriveIsMountedOnDriveLetter),
  1453. // We don't autorun if this is a restricted drive
  1454. AR_ENTRY(0, DT_ANYTYPE & ~DT_REMOTE, CT_ANYCONTENT, CANCEL_AUTOPLAY_ONTRUE, _acDriveIsRestricted),
  1455. // Add the Autoplay Verb
  1456. AR_ENTRY(1, DT_ANYTYPE & ~DT_REMOTE, CT_ANYCONTENT & ~CT_AUTORUNINF, SKIPDEPENDENTS_ONFALSE, _acAddAutoplayVerb),
  1457. // We don't autorun if the Shift key is down
  1458. AR_ENTRY(0, DT_ANYTYPE, CT_ANYCONTENT, CANCEL_AUTOPLAY_ONTRUE, _acShiftKeyDown),
  1459. // We don't autorun if a laptop was just docked. All devices in the craddle come as nhew devices.
  1460. AR_ENTRY(0, DT_ANYTYPE & ~DT_REMOTE, CT_ANYCONTENT, CANCEL_AUTOPLAY_ONTRUE, _acWasjustDocked),
  1461. // We don't autorun if the Current Desktop is not the active console desktop
  1462. AR_ENTRY(0, DT_ANYTYPE, CT_ANYCONTENT, CANCEL_AUTOPLAY_ONFALSE, _acCurrentDesktopIsActiveConsole),
  1463. // We don't autorun if the Current Desktop is not the active console desktop
  1464. AR_ENTRY(0, DT_ANYTYPE, CT_ANYCONTENT, CANCEL_AUTOPLAY_ONTRUE, _acDirectXAppRunningFullScreen),
  1465. // Remote drive always Autorun (mostly opening folder)
  1466. AR_ENTRY(1, DT_REMOTE, CT_ANYCONTENT, SKIPDEPENDENTS_ONFALSE, _acForegroundAppAllowsAutorun),
  1467. AR_ENTRY(1, DT_REMOTE, CT_ANYCONTENT, SKIPDEPENDENTS_ONFALSE, _acQueryCancelAutoplayAllowsAutorun),
  1468. AR_ENTRY(2 | LEVEL_EXECUTE, DT_REMOTE, CT_ANYCONTENT, NOTAPPLICABLE_ONANY, _acShellExecuteDriveAutorunINF),
  1469. // Autorun.inf
  1470. AR_ENTRY(1, DT_ANYTYPE & ~DT_REMOVABLEDISK, CT_AUTORUNINF, SKIPDEPENDENTS_ONFALSE, _acHasAutorunCommand),
  1471. AR_ENTRY(2, DT_ANYTYPE & ~DT_REMOVABLEDISK, CT_AUTORUNINF, SKIPDEPENDENTS_ONTRUE, _acHasUseAutoPLAY),
  1472. AR_ENTRY(3, DT_ANYTYPE & ~DT_REMOVABLEDISK, CT_AUTORUNINF, CANCEL_AUTOPLAY_ONFALSE, _acForegroundAppAllowsAutorun),
  1473. AR_ENTRY(3, DT_ANYTYPE & ~DT_REMOVABLEDISK, CT_AUTORUNINF, CANCEL_AUTOPLAY_ONFALSE, _acQueryCancelAutoplayAllowsAutorun),
  1474. AR_ENTRY(4 | LEVEL_EXECUTE, DT_ANYCDDRIVES, CT_AUTORUNINF, NOTAPPLICABLE_ONANY, _acShellExecuteDriveAutorunINF),
  1475. // CD Audio
  1476. AR_ENTRY(1, DT_ANYCDDRIVES, CT_CDAUDIO, CANCEL_AUTOPLAY_ONFALSE, _acForegroundAppAllowsAutorun),
  1477. AR_ENTRY(1, DT_ANYCDDRIVES, CT_CDAUDIO, CANCEL_AUTOPLAY_ONFALSE, _acQueryCancelAutoplayAllowsAutorun),
  1478. AR_ENTRY(2, DT_ANYCDDRIVES, CT_CDAUDIO, SKIPDEPENDENTS_ONFALSE, _acUserHasSelectedApplication),
  1479. AR_ENTRY(3 | LEVEL_EXECUTE, DT_ANYCDDRIVES, CT_CDAUDIO, NOTAPPLICABLE_ONANY, _acExecuteAutoplayDefault),
  1480. AR_ENTRY(LEVEL_EXECUTE | 1, DT_ANYCDDRIVES, CT_CDAUDIO, NOTAPPLICABLE_ONANY, _acPromptUser),
  1481. // DVD Movie
  1482. AR_ENTRY(1, DT_ANYCDDRIVES, CT_DVDMOVIE, CANCEL_AUTOPLAY_ONFALSE, _acForegroundAppAllowsAutorun),
  1483. AR_ENTRY(1, DT_ANYCDDRIVES, CT_DVDMOVIE, CANCEL_AUTOPLAY_ONFALSE, _acQueryCancelAutoplayAllowsAutorun),
  1484. AR_ENTRY(2, DT_ANYCDDRIVES, CT_DVDMOVIE, SKIPDEPENDENTS_ONFALSE, _acUserHasSelectedApplication),
  1485. AR_ENTRY(3 | LEVEL_EXECUTE, DT_ANYCDDRIVES, CT_DVDMOVIE, NOTAPPLICABLE_ONANY, _acExecuteAutoplayDefault),
  1486. AR_ENTRY(LEVEL_EXECUTE | 1, DT_ANYCDDRIVES, CT_DVDMOVIE, NOTAPPLICABLE_ONANY, _acPromptUser),
  1487. // Writable CDs
  1488. AR_ENTRY(1, DT_ANYCDDRIVES, CT_BLANKCDWRITABLE, CANCEL_AUTOPLAY_ONFALSE, _acForegroundAppAllowsAutorun),
  1489. AR_ENTRY(1, DT_ANYCDDRIVES, CT_BLANKCDWRITABLE, CANCEL_AUTOPLAY_ONFALSE, _acQueryCancelAutoplayAllowsAutorun),
  1490. AR_ENTRY(2, DT_ANYCDDRIVES, CT_BLANKCDWRITABLE, SKIPDEPENDENTS_ONFALSE, _acUserHasSelectedApplication),
  1491. AR_ENTRY(3 | LEVEL_EXECUTE, DT_ANYCDDRIVES, CT_BLANKCDWRITABLE, NOTAPPLICABLE_ONANY, _acExecuteAutoplayDefault),
  1492. AR_ENTRY(LEVEL_EXECUTE | 1, DT_ANYCDDRIVES, CT_BLANKCDWRITABLE, NOTAPPLICABLE_ONANY, _acPromptUser),
  1493. // Writable DVDs
  1494. AR_ENTRY(LEVEL_SKIP | 1, DT_ANYCDDRIVES, CT_BLANKCDWRITABLE, CANCEL_AUTOPLAY_ONFALSE, _acForegroundAppAllowsAutorun),
  1495. AR_ENTRY(LEVEL_SKIP | 1, DT_ANYCDDRIVES, CT_BLANKCDWRITABLE, CANCEL_AUTOPLAY_ONFALSE, _acQueryCancelAutoplayAllowsAutorun),
  1496. AR_ENTRY(LEVEL_SKIP | 2, DT_ANYCDDRIVES, CT_BLANKCDWRITABLE, SKIPDEPENDENTS_ONFALSE, _acUserHasSelectedApplication),
  1497. AR_ENTRY(LEVEL_SKIP | 3 | LEVEL_EXECUTE, DT_ANYDVDDRIVES, CT_BLANKDVDWRITABLE, NOTAPPLICABLE_ONANY, _acExecuteAutoplayDefault),
  1498. AR_ENTRY(LEVEL_SKIP | LEVEL_EXECUTE | 1, DT_ANYDVDDRIVES, CT_BLANKDVDWRITABLE, NOTAPPLICABLE_ONANY, _acPromptUser),
  1499. // Mixed content
  1500. AR_ENTRY(1, DT_ANYTYPE & ~DT_REMOTE, CT_ANYAUTOPLAYCONTENT, SKIPDEPENDENTS_ONFALSE, _acIsMixedContent),
  1501. AR_ENTRY(2, DT_ANYTYPE & ~DT_REMOTE, CT_ANYAUTOPLAYCONTENT, SKIPDEPENDENTS_ONTRUE, _acUserHasSelectedApplication),
  1502. AR_ENTRY(3, DT_ANYTYPE & ~DT_REMOTE, CT_ANYAUTOPLAYCONTENT, CANCEL_AUTOPLAY_ONFALSE, _acQueryCancelAutoplayAllowsAutorun),
  1503. AR_ENTRY(4 | LEVEL_EXECUTE, DT_ANYTYPE & ~DT_REMOTE, CT_ANYAUTOPLAYCONTENT, NOTAPPLICABLE_ONANY, _acPromptUser),
  1504. AR_ENTRY(LEVEL_EXECUTE | 2, DT_ANYTYPE & ~DT_REMOTE, CT_ANYAUTOPLAYCONTENT, NOTAPPLICABLE_ONANY, _acExecuteAutoplayDefault),
  1505. // Single Autoplay content
  1506. AR_ENTRY(1, DT_ANYTYPE & ~DT_REMOTE, CT_ANYAUTOPLAYCONTENT, CANCEL_AUTOPLAY_ONFALSE, _acQueryCancelAutoplayAllowsAutorun),
  1507. AR_ENTRY(2, DT_ANYTYPE & ~DT_REMOTE, CT_ANYAUTOPLAYCONTENT, SKIPDEPENDENTS_ONTRUE, _acUserHasSelectedApplication),
  1508. AR_ENTRY(3 | LEVEL_EXECUTE, DT_ANYTYPE & ~DT_REMOTE, CT_ANYAUTOPLAYCONTENT, NOTAPPLICABLE_ONANY, _acPromptUser),
  1509. AR_ENTRY(LEVEL_EXECUTE | 2, DT_ANYTYPE & ~DT_REMOTE, CT_ANYAUTOPLAYCONTENT, NOTAPPLICABLE_ONANY, _acExecuteAutoplayDefault),
  1510. // Unknown content
  1511. AR_ENTRY(1, DT_ANYREMOVABLEMEDIADRIVES, CT_UNKNOWNCONTENT, CANCEL_AUTOPLAY_ONFALSE, _acForegroundAppAllowsAutorun),
  1512. AR_ENTRY(1, DT_ANYREMOVABLEMEDIADRIVES, CT_UNKNOWNCONTENT, CANCEL_AUTOPLAY_ONFALSE, _acQueryCancelAutoplayAllowsAutorun),
  1513. // If we should not sniff, we should not open a folder either
  1514. AR_ENTRY(2, DT_ANYREMOVABLEMEDIADRIVES, CT_UNKNOWNCONTENT, SKIPDEPENDENTS_ONFALSE, _acShouldSniff),
  1515. AR_ENTRY(3 | LEVEL_EXECUTE, DT_ANYREMOVABLEMEDIADRIVES, CT_UNKNOWNCONTENT, NOTAPPLICABLE_ONANY, _acShellExecuteDriveAutorunINF),
  1516. // Weird CDs have autorun.inf but no autorun command
  1517. AR_ENTRY(2, DT_ANYREMOVABLEMEDIADRIVES, CT_AUTORUNINF, SKIPDEPENDENTS_ONTRUE, _acHasAutorunCommand),
  1518. AR_ENTRY(3 | LEVEL_EXECUTE, DT_ANYREMOVABLEMEDIADRIVES, CT_AUTORUNINF, NOTAPPLICABLE_ONANY, _acShellExecuteDriveAutorunINF),
  1519. // Former ShellOpen, basically we ShellExecute whatever drives except CD drives if the shell is in the foreground
  1520. AR_ENTRY(1, ~DT_ANYCDDRIVES, CT_ANYCONTENT & ~CT_ANYAUTOPLAYCONTENT, SKIPDEPENDENTS_ONFALSE, _acShellIsForegroundApp),
  1521. AR_ENTRY(2, ~DT_ANYCDDRIVES, CT_ANYCONTENT & ~CT_ANYAUTOPLAYCONTENT, CANCEL_AUTOPLAY_ONTRUE, _acAlwaysReturnsTRUE),
  1522. // Additonnal restrictions on Fixed disk drive
  1523. AR_ENTRY(3, DT_FIXEDDISK, CT_ANYCONTENT & ~CT_ANYAUTOPLAYCONTENT, CANCEL_AUTOPLAY_ONFALSE, _acDriveIsFormatted),
  1524. AR_ENTRY(4, DT_FIXEDDISK, CT_ANYCONTENT & ~CT_ANYAUTOPLAYCONTENT, CANCEL_AUTOPLAY_ONTRUE, _acOSIsServer),
  1525. AR_ENTRY(5, DT_FIXEDDISK, CT_ANYCONTENT & ~CT_ANYAUTOPLAYCONTENT, CANCEL_AUTOPLAY_ONTRUE, _acIsDockedLaptop),
  1526. AR_ENTRY(6, DT_FIXEDDISK, CT_ANYCONTENT & ~CT_ANYAUTOPLAYCONTENT, CANCEL_AUTOPLAY_ONFALSE, _acForegroundAppAllowsAutorun),
  1527. AR_ENTRY(6, DT_FIXEDDISK, CT_ANYCONTENT & ~CT_ANYAUTOPLAYCONTENT, CANCEL_AUTOPLAY_ONFALSE, _acQueryCancelAutoplayAllowsAutorun),
  1528. AR_ENTRY(7 | LEVEL_EXECUTE, DT_ANYTYPE, CT_ANYCONTENT & ~CT_ANYAUTOPLAYCONTENT, NOTAPPLICABLE_ONANY, _acShellExecuteDriveAutorunINF),
  1529. // Non Fixed Disk drives
  1530. AR_ENTRY(3, ~DT_FIXEDDISK, CT_ANYCONTENT & ~CT_ANYAUTOPLAYCONTENT, CANCEL_AUTOPLAY_ONFALSE, _acForegroundAppAllowsAutorun),
  1531. AR_ENTRY(3, ~DT_FIXEDDISK, CT_ANYCONTENT & ~CT_ANYAUTOPLAYCONTENT, CANCEL_AUTOPLAY_ONFALSE, _acQueryCancelAutoplayAllowsAutorun),
  1532. AR_ENTRY(4 | LEVEL_EXECUTE, ~DT_FIXEDDISK, CT_ANYCONTENT & ~CT_ANYAUTOPLAYCONTENT, NOTAPPLICABLE_ONANY, _acShellExecuteDriveAutorunINF),
  1533. };
  1534. // This array will be dumped in the registry under the Volume GUID of the
  1535. // drive in a value named _AutorunStatus
  1536. //
  1537. // Each byte represents an entry in the above table. Following is the
  1538. // meaning of each byte:
  1539. //
  1540. // 01: Condition was TRUE
  1541. // 00: Condition was FALSE
  1542. // CF: ContentType condition was failed
  1543. // DF: DriveType condition was failed
  1544. // 5F: Condition was skipped (5 looks like an 'S' :)
  1545. // EE: Condition was executed
  1546. // FF: Never got there
  1547. // Use a struct to avoid alignement issues
  1548. #pragma pack(push, 4)
  1549. struct AUTORUNSTATUS
  1550. {
  1551. BYTE _rgbAutorunStatus[ARRAYSIZE(_rgAutorun)];
  1552. DWORD dwDriveType;
  1553. DWORD dwContentType;
  1554. };
  1555. #pragma pack(pop)
  1556. static AUTORUNSTATUS s_autorunstatus;
  1557. // static
  1558. void CMountPoint::DoAutorun(LPCWSTR pszDrive, DWORD dwAutorunFlags)
  1559. {
  1560. CMountPoint* pmtpt = GetMountPoint(pszDrive);
  1561. FillMemory(s_autorunstatus._rgbAutorunStatus, sizeof(s_autorunstatus._rgbAutorunStatus), -1);
  1562. if (pmtpt)
  1563. {
  1564. CAutoPlayParams app(pszDrive, pmtpt, dwAutorunFlags);
  1565. if (AUTORUNFLAG_MENUINVOKED & dwAutorunFlags)
  1566. {
  1567. _acPromptUser(GetForegroundWindow(), &app);
  1568. }
  1569. else
  1570. {
  1571. _DoAutorunHelper(&app);
  1572. }
  1573. pmtpt->Release();
  1574. }
  1575. }
  1576. void CAutoPlayParams::_TrySniff()
  1577. {
  1578. if (!(APS_DID_SNIFF & _state))
  1579. {
  1580. if (_ShouldSniffDrive(TRUE))
  1581. {
  1582. DWORD dwFound;
  1583. if (SUCCEEDED(_Sniff(&dwFound)))
  1584. {
  1585. _dwContentType |= dwFound;
  1586. }
  1587. }
  1588. _state |= APS_DID_SNIFF;
  1589. }
  1590. }
  1591. BOOL CAutoPlayParams::IsContentTypePresent(DWORD dwContentType)
  1592. {
  1593. BOOL fRet;
  1594. if (CT_ANYCONTENT == dwContentType)
  1595. {
  1596. fRet = TRUE;
  1597. }
  1598. else
  1599. {
  1600. // We special case this because we do not want to sniff at this point
  1601. if ((CT_ANYCONTENT & ~CT_AUTORUNINF) == dwContentType)
  1602. {
  1603. if (CT_AUTORUNINF == _dwContentType)
  1604. {
  1605. fRet = FALSE;
  1606. }
  1607. else
  1608. {
  1609. // Anything else is good
  1610. fRet = TRUE;
  1611. }
  1612. }
  1613. else
  1614. {
  1615. if (CT_ANYAUTOPLAYCONTENT & dwContentType)
  1616. {
  1617. _TrySniff();
  1618. }
  1619. fRet = !!(dwContentType & _dwContentType);
  1620. }
  1621. }
  1622. return fRet;
  1623. }
  1624. void CAutoPlayParams::ForceSniff()
  1625. {
  1626. if (AUTORUNFLAG_MENUINVOKED & _dwAutorunFlags)
  1627. {
  1628. _TrySniff();
  1629. }
  1630. }
  1631. // static
  1632. void CMountPoint::_DoAutorunHelper(CAutoPlayParams *papp)
  1633. {
  1634. DWORD dwMaxLevelToProcess = 0;
  1635. BOOL fStop = FALSE;
  1636. HWND hwndForeground = GetForegroundWindow();
  1637. for (DWORD dwStep = 0; !fStop && (dwStep < ARRAYSIZE(_rgAutorun)); ++dwStep)
  1638. {
  1639. if (!(_rgAutorun[dwStep].dwNestingLevel & LEVEL_SKIP))
  1640. {
  1641. if ((_rgAutorun[dwStep].dwNestingLevel & LEVEL_REALLEVELMASK) <= dwMaxLevelToProcess)
  1642. {
  1643. BOOL fConditionResult = FALSE;
  1644. // We do not want to Cancel the whole Autoplay operation if we do not get a
  1645. // match for a drive type or content type. We do the Cancel Autoplay only
  1646. // if the condition was evaluated.
  1647. BOOL fConditionEvaluated = FALSE;
  1648. if (_rgAutorun[dwStep].dwMtPtDriveType & papp->DriveType())
  1649. {
  1650. if (papp->IsContentTypePresent(_rgAutorun[dwStep].dwMtPtContentType))
  1651. {
  1652. if (!(_rgAutorun[dwStep].dwNestingLevel & LEVEL_EXECUTE))
  1653. {
  1654. fConditionResult = ((_rgAutorun[dwStep].fct)(hwndForeground, papp));
  1655. s_autorunstatus._rgbAutorunStatus[dwStep] = fConditionResult ? 1 : 0;
  1656. fConditionEvaluated = TRUE;
  1657. }
  1658. else
  1659. {
  1660. // LEVEL_EXECUTE
  1661. #ifdef DEBUG
  1662. TraceMsg(TF_MOUNTPOINT, "AUTORUN[%d]: EXECUTING -> %s", dwStep, _rgAutorun[dwStep].pszDebug);
  1663. #endif
  1664. _rgAutorun[dwStep].fct(hwndForeground, papp);
  1665. // 2 execute
  1666. s_autorunstatus._rgbAutorunStatus[dwStep] = 0xEE;
  1667. // We're done
  1668. fStop = TRUE;
  1669. }
  1670. }
  1671. else
  1672. {
  1673. #ifdef DEBUG
  1674. TraceMsg(TF_MOUNTPOINT, "AUTORUN[%d]: NO MATCH on CONTENTTYPE, %s ", dwStep, _rgAutorun[dwStep].pszDebug);
  1675. #endif
  1676. s_autorunstatus._rgbAutorunStatus[dwStep] = 0xCF;
  1677. }
  1678. }
  1679. else
  1680. {
  1681. #ifdef DEBUG
  1682. TraceMsg(TF_MOUNTPOINT, "AUTORUN[%d]: NO MATCH on DRIVETYPE, %s ", dwStep, _rgAutorun[dwStep].pszDebug);
  1683. #endif
  1684. s_autorunstatus._rgbAutorunStatus[dwStep] = 0xDF;
  1685. }
  1686. if (!fStop)
  1687. {
  1688. if (fConditionResult)
  1689. {
  1690. #ifdef DEBUG
  1691. TraceMsg(TF_MOUNTPOINT, "AUTORUN[%d]: TRUE -> %s", dwStep, _rgAutorun[dwStep].pszDebug);
  1692. #endif
  1693. switch (_rgAutorun[dwStep].dwReturnValueHandling)
  1694. {
  1695. case SKIPDEPENDENTS_ONTRUE:
  1696. dwMaxLevelToProcess = _rgAutorun[dwStep].dwNestingLevel & LEVEL_REALLEVELMASK;
  1697. break;
  1698. case CANCEL_AUTOPLAY_ONTRUE:
  1699. if (fConditionEvaluated)
  1700. {
  1701. fStop = TRUE;
  1702. }
  1703. break;
  1704. default:
  1705. dwMaxLevelToProcess = (_rgAutorun[dwStep].dwNestingLevel & LEVEL_REALLEVELMASK) + 1;
  1706. break;
  1707. case NOTAPPLICABLE_ONANY:
  1708. break;
  1709. }
  1710. }
  1711. else
  1712. {
  1713. #ifdef DEBUG
  1714. TraceMsg(TF_MOUNTPOINT, "AUTORUN[%d]: FALSE -> %s", dwStep, _rgAutorun[dwStep].pszDebug);
  1715. #endif
  1716. switch (_rgAutorun[dwStep].dwReturnValueHandling)
  1717. {
  1718. case SKIPDEPENDENTS_ONFALSE:
  1719. dwMaxLevelToProcess = _rgAutorun[dwStep].dwNestingLevel & LEVEL_REALLEVELMASK;
  1720. break;
  1721. case CANCEL_AUTOPLAY_ONFALSE:
  1722. if (fConditionEvaluated)
  1723. {
  1724. fStop = TRUE;
  1725. }
  1726. break;
  1727. default:
  1728. dwMaxLevelToProcess = (_rgAutorun[dwStep].dwNestingLevel & LEVEL_REALLEVELMASK) + 1;
  1729. break;
  1730. case NOTAPPLICABLE_ONANY:
  1731. break;
  1732. }
  1733. }
  1734. }
  1735. }
  1736. else
  1737. {
  1738. #ifdef DEBUG
  1739. TraceMsg(TF_MOUNTPOINT, "AUTORUN[%d]: SKIPPING , %s ", dwStep, _rgAutorun[dwStep].pszDebug);
  1740. #endif
  1741. s_autorunstatus._rgbAutorunStatus[dwStep] = 0x5F;
  1742. }
  1743. }
  1744. else
  1745. {
  1746. #ifdef DEBUG
  1747. TraceMsg(TF_MOUNTPOINT, "AUTORUN[%d]: LVL-SKIP , %s ", dwStep, _rgAutorun[dwStep].pszDebug);
  1748. #endif
  1749. s_autorunstatus._rgbAutorunStatus[dwStep] = 0x5F;
  1750. }
  1751. }
  1752. s_autorunstatus.dwDriveType = papp->DriveType();
  1753. s_autorunstatus.dwContentType = papp->ContentType();
  1754. papp->MountPoint()->SetAutorunStatus((BYTE*)&s_autorunstatus, sizeof(s_autorunstatus));
  1755. }
  1756. DWORD _DoDWORDMapping(DWORD dwLeft, const TWODWORDS* rgtwodword, DWORD ctwodword, BOOL fORed)
  1757. {
  1758. DWORD dwRight = 0;
  1759. for (DWORD dw = 0; dw < ctwodword; ++dw)
  1760. {
  1761. if (fORed)
  1762. {
  1763. if (dwLeft & rgtwodword[dw].dwLeft)
  1764. {
  1765. dwRight |= rgtwodword[dw].dwRight;
  1766. }
  1767. }
  1768. else
  1769. {
  1770. if (dwLeft == rgtwodword[dw].dwLeft)
  1771. {
  1772. dwRight = rgtwodword[dw].dwRight;
  1773. break;
  1774. }
  1775. }
  1776. }
  1777. return dwRight;
  1778. }
  1779. STDMETHODIMP CSniffDrive::QueryInterface(REFIID riid, void **ppv)
  1780. {
  1781. static const QITAB qit[] =
  1782. {
  1783. QITABENT(CSniffDrive, INamespaceWalkCB),
  1784. { 0 },
  1785. };
  1786. return QISearch(this, qit, riid, ppv);
  1787. }
  1788. STDMETHODIMP CSniffDrive::FoundItem(IShellFolder *psf, LPCITEMIDLIST pidl)
  1789. {
  1790. // include everything
  1791. HRESULT hr = S_OK;
  1792. if (!_pne || !_pne->fStopSniffing)
  1793. {
  1794. // if we found everything we dont need to worry about sniffing
  1795. // now we are just populating the dataobject
  1796. if (!_FoundEverything())
  1797. {
  1798. PERCEIVED gen = GetPerceivedType(psf, pidl);
  1799. if (GEN_IMAGE == gen)
  1800. {
  1801. _dwFound |= CT_AUTOPLAYPIX;
  1802. }
  1803. else if (GEN_AUDIO == gen)
  1804. {
  1805. _dwFound |= CT_AUTOPLAYMUSIC;
  1806. }
  1807. else if (GEN_VIDEO == gen)
  1808. {
  1809. _dwFound |= CT_AUTOPLAYMOVIE;
  1810. }
  1811. else
  1812. {
  1813. _dwFound |= CT_UNKNOWNCONTENT;
  1814. }
  1815. hr = S_OK;
  1816. }
  1817. }
  1818. else
  1819. {
  1820. hr = E_FAIL;
  1821. }
  1822. // we never want the results on the sniff
  1823. return hr;
  1824. }
  1825. STDMETHODIMP CSniffDrive::EnterFolder(IShellFolder *psf, LPCITEMIDLIST pidl)
  1826. {
  1827. return S_OK;
  1828. }
  1829. STDMETHODIMP CSniffDrive::LeaveFolder(IShellFolder *psf, LPCITEMIDLIST pidl)
  1830. {
  1831. return S_OK;
  1832. }
  1833. STDMETHODIMP CSniffDrive::InitializeProgressDialog(LPWSTR *ppszTitle, LPWSTR *ppszCancel)
  1834. {
  1835. *ppszCancel = NULL; // use default
  1836. TCHAR szMsg[256];
  1837. LoadString(g_hinst, IDS_AP_SNIFFPROGRESSDIALOG, szMsg, ARRAYSIZE(szMsg));
  1838. return SHStrDup(szMsg, ppszTitle);
  1839. }
  1840. // static
  1841. HRESULT CSniffDrive::Init(HANDLE hThreadSCN)
  1842. {
  1843. HRESULT hr;
  1844. if (DuplicateHandle(GetCurrentProcess(), hThreadSCN, GetCurrentProcess(),
  1845. &_hThreadSCN, THREAD_ALL_ACCESS, FALSE, 0))
  1846. {
  1847. hr = S_OK;
  1848. }
  1849. else
  1850. {
  1851. hr = E_FAIL;
  1852. }
  1853. return S_OK;
  1854. }
  1855. // static
  1856. HRESULT CSniffDrive::CleanUp()
  1857. {
  1858. if (_dpaNotifs)
  1859. {
  1860. // We should not need to delete the items, they should all be removed. Even
  1861. // if they're, we should leave them there since something will probably try
  1862. // to access them.
  1863. _dpaNotifs.Destroy();
  1864. _dpaNotifs = NULL;
  1865. }
  1866. if (_hThreadSCN)
  1867. {
  1868. CloseHandle(_hThreadSCN);
  1869. _hThreadSCN = NULL;
  1870. }
  1871. return S_OK;
  1872. }
  1873. // static
  1874. HRESULT CSniffDrive::InitNotifyWindow(HWND hwnd)
  1875. {
  1876. _hwndNotify = hwnd;
  1877. return S_OK;
  1878. }
  1879. HRESULT CSniffDrive::RegisterForNotifs(LPCWSTR pszDeviceIDVolume)
  1880. {
  1881. HRESULT hr;
  1882. _pne = new PNPNOTIFENTRY();
  1883. if (_pne)
  1884. {
  1885. HANDLE hDevice = CreateFile(pszDeviceIDVolume, FILE_READ_ATTRIBUTES,
  1886. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
  1887. if (INVALID_HANDLE_VALUE != hDevice)
  1888. {
  1889. DEV_BROADCAST_HANDLE dbhNotifFilter = {0};
  1890. // Assume failure
  1891. hr = E_FAIL;
  1892. dbhNotifFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
  1893. dbhNotifFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
  1894. dbhNotifFilter.dbch_handle = hDevice;
  1895. _pne->hdevnotify = RegisterDeviceNotification(_hwndNotify, &dbhNotifFilter,
  1896. DEVICE_NOTIFY_WINDOW_HANDLE);
  1897. if (_pne->hdevnotify)
  1898. {
  1899. _pne->AddRef();
  1900. if (QueueUserAPC(CSniffDrive::_RegisterForNotifsHelper, _hThreadSCN, (ULONG_PTR)_pne))
  1901. {
  1902. hr = S_OK;
  1903. }
  1904. else
  1905. {
  1906. _pne->Release();
  1907. }
  1908. }
  1909. CloseHandle(hDevice);
  1910. }
  1911. else
  1912. {
  1913. hr = E_FAIL;
  1914. }
  1915. if (FAILED(hr))
  1916. {
  1917. // Something must have gone wrong
  1918. _pne->Release();
  1919. _pne = NULL;
  1920. }
  1921. }
  1922. else
  1923. {
  1924. hr = E_OUTOFMEMORY;
  1925. }
  1926. return hr;
  1927. }
  1928. HRESULT CSniffDrive::UnregisterForNotifs()
  1929. {
  1930. UnregisterDeviceNotification(_pne->hdevnotify);
  1931. QueueUserAPC(CSniffDrive::_UnregisterForNotifsHelper, _hThreadSCN, (ULONG_PTR)_pne);
  1932. _pne->Release();
  1933. _pne = NULL;
  1934. return S_OK;
  1935. }
  1936. // static
  1937. void CALLBACK CSniffDrive::_RegisterForNotifsHelper(ULONG_PTR ul)
  1938. {
  1939. PNPNOTIFENTRY* pne = (PNPNOTIFENTRY*)ul;
  1940. if (!_dpaNotifs)
  1941. {
  1942. _dpaNotifs.Create(1);
  1943. }
  1944. if (_dpaNotifs)
  1945. {
  1946. // We do not check the return value. We cannot free it, since the thread that
  1947. // queued this APC to us, expect this chunk of mem to be there until it calls
  1948. // UnregisterNotify. We'll leak it. Hopefully, this won't happen often.
  1949. _dpaNotifs.AppendPtr(pne);
  1950. }
  1951. }
  1952. // static
  1953. void CALLBACK CSniffDrive::_UnregisterForNotifsHelper(ULONG_PTR ul)
  1954. {
  1955. PNPNOTIFENTRY* pne = (PNPNOTIFENTRY*)ul;
  1956. if (_dpaNotifs)
  1957. {
  1958. int cItem = _dpaNotifs.GetPtrCount();
  1959. for (int i = 0; i < cItem; ++i)
  1960. {
  1961. PNPNOTIFENTRY* pneTmp = _dpaNotifs.GetPtr(i);
  1962. if (pneTmp->hdevnotify == pne->hdevnotify)
  1963. {
  1964. CloseHandle(pne->hThread);
  1965. _dpaNotifs.DeletePtr(i);
  1966. pne->Release();
  1967. break;
  1968. }
  1969. }
  1970. }
  1971. }
  1972. // static
  1973. HRESULT CSniffDrive::HandleNotif(HDEVNOTIFY hdevnotify)
  1974. {
  1975. int cItem = _dpaNotifs ? _dpaNotifs.GetPtrCount() : 0;
  1976. for (int i = 0; i < cItem; ++i)
  1977. {
  1978. PNPNOTIFENTRY* pneTmp = _dpaNotifs.GetPtr(i);
  1979. if (pneTmp->hdevnotify == hdevnotify)
  1980. {
  1981. pneTmp->fStopSniffing = TRUE;
  1982. // We don't check the return value. The worst that will happen is that this
  1983. // fails and we'll return too early and PnP will prompt the user to reboot.
  1984. // Wait 2 minutes
  1985. WaitForSingleObjectEx(pneTmp->hThread, 2 * 60 * 1000, FALSE);
  1986. break;
  1987. }
  1988. }
  1989. return S_OK;
  1990. }
  1991. BOOL CSniffDrive::_FoundEverything()
  1992. {
  1993. return (_dwFound & DRIVEHAS_EVERYTHING) == DRIVEHAS_EVERYTHING;
  1994. }
  1995. CSniffDrive::CSniffDrive() : _dwFound(0)
  1996. {}
  1997. CSniffDrive::~CSniffDrive()
  1998. {}
  1999. void CMountPoint::SetAutorunStatus(BYTE* rgb, DWORD cbSize)
  2000. {
  2001. RSSetBinaryValue(NULL, TEXT("_AutorunStatus"), rgb, cbSize);
  2002. }
  2003. class CAutoPlayVerb : public IDropTarget
  2004. {
  2005. public:
  2006. CAutoPlayVerb() : _cRef(1) {}
  2007. // IUnknown refcounting
  2008. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  2009. STDMETHODIMP_(ULONG) AddRef(void)
  2010. {
  2011. return ++_cRef;
  2012. }
  2013. STDMETHODIMP_(ULONG) Release(void)
  2014. {
  2015. if (--_cRef > 0)
  2016. return _cRef;
  2017. delete this;
  2018. return 0;
  2019. }
  2020. // IDropTarget ***
  2021. STDMETHODIMP DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  2022. STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  2023. STDMETHODIMP DragLeave(void);
  2024. STDMETHODIMP Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  2025. protected:
  2026. LONG _cRef;
  2027. };
  2028. HRESULT CAutoPlayVerb::QueryInterface(REFIID riid, void **ppv)
  2029. {
  2030. static const QITAB qit[] =
  2031. {
  2032. QITABENT(CAutoPlayVerb, IDropTarget),
  2033. { 0 },
  2034. };
  2035. return QISearch(this, qit, riid, ppv);
  2036. }
  2037. // IDropTarget::DragEnter
  2038. HRESULT CAutoPlayVerb::DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  2039. {
  2040. *pdwEffect = DROPEFFECT_COPY;
  2041. return S_OK;;
  2042. }
  2043. // IDropTarget::DragOver
  2044. HRESULT CAutoPlayVerb::DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  2045. {
  2046. *pdwEffect = DROPEFFECT_COPY;
  2047. return S_OK;;
  2048. }
  2049. // IDropTarget::DragLeave
  2050. HRESULT CAutoPlayVerb::DragLeave(void)
  2051. {
  2052. return S_OK;
  2053. }
  2054. STDAPI CAutoPlayVerb_CreateInstance(IUnknown* pUnkOuter, REFIID riid, void **ppv)
  2055. {
  2056. HRESULT hr = E_OUTOFMEMORY;
  2057. *ppv = NULL;
  2058. // aggregation checking is handled in class factory
  2059. CAutoPlayVerb* p = new CAutoPlayVerb();
  2060. if (p)
  2061. {
  2062. hr = p->QueryInterface(riid, ppv);
  2063. p->Release();
  2064. }
  2065. return hr;
  2066. }
  2067. STDAPI SHChangeNotifyAutoplayDrive(PCWSTR pszDrive);
  2068. // IDropTarget::DragDrop
  2069. HRESULT CAutoPlayVerb::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  2070. {
  2071. *pdwEffect = DROPEFFECT_COPY;
  2072. // start the AutoPlayDialog
  2073. WCHAR szDrive[4];
  2074. HRESULT hr = PathFromDataObject(pdtobj, szDrive, ARRAYSIZE(szDrive));
  2075. if (SUCCEEDED(hr))
  2076. {
  2077. hr = SHChangeNotifyAutoplayDrive(szDrive);
  2078. }
  2079. return hr;
  2080. }
  2081. DWORD CALLBACK _AutorunPromptProc(void *pv)
  2082. {
  2083. WCHAR szDrive[4];
  2084. CMountPoint::DoAutorun(PathBuildRoot(szDrive, PtrToInt(pv)), AUTORUNFLAG_MENUINVOKED);
  2085. return 0;
  2086. }
  2087. void CMountPoint::DoAutorunPrompt(WPARAM iDrive)
  2088. {
  2089. SHCreateThread(_AutorunPromptProc, (void *)iDrive, CTF_COINIT | CTF_REF_COUNTED, NULL);
  2090. }
  2091. STDAPI_(void) Activate_RunDLL(HWND hwndStub, HINSTANCE hAppInstance, LPWSTR lpwszCmdLine, int nCmdShow)
  2092. {
  2093. DWORD dwProcessID;
  2094. HWND hwnd = GetShellWindow();
  2095. GetWindowThreadProcessId(hwnd, &dwProcessID);
  2096. AllowSetForegroundWindow(dwProcessID);
  2097. }