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.

408 lines
14 KiB

  1. /*-----------------------------------------------------------------------------+
  2. | FIXREG.C |
  3. | |
  4. | Publisher and Video For Windows make evil changes to the registry |
  5. | when they are installed. Look for these changes. If they are spotted |
  6. | then put up a message box to warn the user and offer the user the chance to |
  7. | correct them (i.e. stuff our version back in) |
  8. | |
  9. | (C) Copyright Microsoft Corporation 1994. All rights reserved. |
  10. | |
  11. | Revision History |
  12. | 10-Aug-1994 Lauriegr Created. |
  13. | |
  14. +-----------------------------------------------------------------------------*/
  15. #include <windows.h>
  16. #include "mplayer.h"
  17. #include "fixreg.h"
  18. #include "registry.h"
  19. /* The idea is to call CheckRegValues(hinst) on a separate thread
  20. (sort of backgroundy thing) and have it just die
  21. quietly if there's no problem. If on the other hand there is a problem
  22. then we need to get the message box up - and it's a VERY BAD IDEA to
  23. try to put a message box up on anything other than the thread that's doing
  24. all the UI (otherwise ScottLu will get you with a weasle word - guaranteed).
  25. So the background thread should PostMessage (Post, don't Send - more weasles)
  26. to the main thread a message to say "WM_BADREG". The main thread should then
  27. wack up the dialog box by calling FixRegValues.
  28. Suggested coding in main thread:
  29. BackgroundRegCheck(hwndmain);
  30. in window proc for hwndmain:
  31. case WM_HEYUP:
  32. // if ( IDOK == MessageBox(hwnd, text, appname, MB_OKCANCEL) )
  33. if ( IDOK == ErrorResBox(hwnd, NULL, MB_OKCANCEL, IDS_APPNAME, IDS_BADREG) )
  34. if (!SetRegValues())
  35. Error(ghwndApp, IDS_FIXREGERROR);
  36. */
  37. /* This is a reg setting to disable the check. */
  38. extern SZCODE aszOptionsSection[];
  39. static SZCODE aszIgnoreRegistryCheck[] = TEXT("Ignore Registry Check");
  40. /* These are the things we check up.
  41. First define them as static strings, since the compiler's not smart enough
  42. to spot common strings.
  43. NOTE - these values are NOT LOCALISED, except for the ones that are.
  44. */
  45. #ifdef CHICAGO_PRODUCT
  46. #define APPNAME TEXT("mplayer.exe")
  47. #define WINDIR TEXT("%s\\") // To be replaced by Windows directory
  48. LPTSTR pWindowsDirectory = NULL;
  49. #else
  50. #define APPNAME TEXT("mplay32.exe")
  51. #define WINDIR
  52. #endif
  53. TCHAR szMPlayer[] = TEXT("MPlayer");
  54. TCHAR szMPlayer_CLSID[] = TEXT("MPlayer\\CLSID");
  55. TCHAR szMPOLE2GUID[] = TEXT("{00022601-0000-0000-C000-000000000046}");
  56. TCHAR szMPCLSID_OLE1GUID[] = TEXT("CLSID\\{0003000E-0000-0000-C000-000000000046}");
  57. TCHAR szMPStdExecute_Server[] = TEXT("MPlayer\\protocol\\StdExecute\\server");
  58. TCHAR szAppName[] = WINDIR APPNAME;
  59. TCHAR szMPShell_Open_Command[] = TEXT("MPlayer\\shell\\open\\command");
  60. TCHAR szAppName_Play_Close[] = WINDIR APPNAME TEXT(" /play /close %1");
  61. TCHAR szMPlayer_insertable[] = TEXT("MPlayer\\insertable");
  62. TCHAR szEmpty[] = TEXT("");
  63. TCHAR szMPStdFileEdit_Handler[] = TEXT("MPlayer\\protocol\\StdFileEditing\\handler");
  64. #ifdef CHICAGO_PRODUCT
  65. TCHAR szMCIOLE[] = WINDIR TEXT("mciole.dll");
  66. #else
  67. TCHAR szMCIOLE16[] = TEXT("mciole16.dll");
  68. TCHAR szMPStdFileEdit_Hand32[] = TEXT("MPlayer\\protocol\\StdFileEditing\\handler32");
  69. TCHAR szMCIOLE32[] = TEXT("mciole32.dll");
  70. #endif
  71. TCHAR szMPStdFileEdit_Package[] = TEXT("MPlayer\\protocol\\StdFileEditing\\PackageObjects");
  72. TCHAR szMPStdFileEdit_Server[] = TEXT("MPlayer\\protocol\\StdFileEditing\\server");
  73. TCHAR szMPStdFileEdit_verb_0[] = TEXT("MPlayer\\protocol\\StdFileEditing\\verb\\0");
  74. TCHAR szMPStdFileEdit_verb_1[] = TEXT("MPlayer\\protocol\\StdFileEditing\\verb\\1");
  75. /* That sleazebag Publisher setup even farts around with these new settings!!
  76. */
  77. TCHAR szAVIStdFileEdit_Server[] = TEXT("AVIFile\\protocol\\StdFileEditing\\server");
  78. TCHAR szMIDStdFileEdit_Server[] = TEXT("MIDFile\\protocol\\StdFileEditing\\server");
  79. TCHAR szServerAVI[] = WINDIR APPNAME TEXT(" /avi");
  80. TCHAR szServerMID[] = WINDIR APPNAME TEXT(" /mid");
  81. /* The following ones DO need to be localised.
  82. They will be loaded in CheckRegValues.
  83. */
  84. #define RES_STR_LEN 40 /* Should be enough as a maximum resource string. */
  85. TCHAR szMediaClip[RES_STR_LEN]; // IDS_CLASSROOT in resources
  86. TCHAR sz_Play[RES_STR_LEN]; // IDS_PLAYVERB in resources
  87. TCHAR sz_Edit[RES_STR_LEN]; // IDS_EDITVERB in resources
  88. TCHAR szAviFile[] = TEXT("AVIFile");
  89. TCHAR szMidFile[] = TEXT("MIDFile");
  90. /* Array of registry value-data pairs to check:
  91. */
  92. LPTSTR RegValues[] =
  93. {
  94. szMPlayer, szMediaClip,
  95. szMPlayer_CLSID, szMPOLE2GUID,
  96. szMPCLSID_OLE1GUID, szMediaClip,
  97. szMPStdExecute_Server, szAppName,
  98. szMPShell_Open_Command, szAppName_Play_Close,
  99. szMPlayer_insertable, szEmpty,
  100. #ifdef CHICAGO_PRODUCT
  101. szMPStdFileEdit_Handler, szMCIOLE,
  102. #else
  103. szMPStdFileEdit_Handler, szMCIOLE16,
  104. szMPStdFileEdit_Hand32, szMCIOLE32,
  105. #endif
  106. szMPStdFileEdit_Package, szEmpty,
  107. szMPStdFileEdit_Server, szAppName,
  108. szMPStdFileEdit_verb_0, sz_Play,
  109. szMPStdFileEdit_verb_1, sz_Edit,
  110. aszKeyAVI, szAviFile,
  111. aszKeyMID, szMidFile,
  112. aszKeyRMI, szMidFile,
  113. szAVIStdFileEdit_Server, szServerAVI,
  114. szMIDStdFileEdit_Server, szServerMID
  115. };
  116. #ifdef CHICAGO_PRODUCT
  117. /* AllocWindowsDirectory
  118. *
  119. * Dynamically allocates a string containing the Windows directory.
  120. * This may be freed using FreeStr().
  121. *
  122. */
  123. LPTSTR AllocWindowsDirectory()
  124. {
  125. UINT cchWinPath;
  126. LPTSTR pWindowsDirectory = NULL;
  127. cchWinPath = GetWindowsDirectory(NULL, 0);
  128. if (cchWinPath > 0)
  129. {
  130. if (pWindowsDirectory = AllocMem(cchWinPath * sizeof(TCHAR)))
  131. {
  132. cchWinPath = GetWindowsDirectory(pWindowsDirectory, cchWinPath);
  133. if (cchWinPath == 0)
  134. {
  135. /* Unlikely, but check anyway:
  136. */
  137. DPF0("GetWindowsDiretory failed: Error %d\n", GetLastError());
  138. *pWindowsDirectory = TEXT('\0');
  139. }
  140. }
  141. }
  142. return pWindowsDirectory;
  143. }
  144. #endif
  145. /* Check that a REG_SZ value in the registry has the value that it should do
  146. Return TRUE if it does, FALSE if it doesn't.
  147. */
  148. BOOL CheckRegValue(HKEY RootKey, LPTSTR KeyName, LPTSTR ShouldBe)
  149. {
  150. DWORD Type;
  151. TCHAR Data[100];
  152. DWORD cData = sizeof(Data);
  153. LONG lRet;
  154. HKEY hkey;
  155. if (ERROR_SUCCESS!=RegOpenKeyEx( RootKey
  156. , KeyName
  157. , 0 /* reserved */
  158. , KEY_QUERY_VALUE
  159. , &hkey
  160. )
  161. )
  162. return FALSE; /* couldn't even open the key */
  163. lRet=RegQueryValueEx( hkey
  164. , NULL /* ValueName */
  165. , NULL /* reserved */
  166. , &Type
  167. , (LPBYTE)Data
  168. , &cData
  169. );
  170. RegCloseKey(hkey); /* no idea what to do if this fails */
  171. if (ERROR_SUCCESS!=lRet) return FALSE; /* couldn't query it */
  172. /* Data, cData and Type give the data, length and type */
  173. if (Type!=REG_SZ) return FALSE;
  174. lRet = lstrcmpi(Data,ShouldBe); /* capture lRet to make debug easier */
  175. return 0==lRet;
  176. } /* CheckRegValue */
  177. /* check the registry for anything evil. Return TRUE if it's OK else FALSE */
  178. BOOL CheckRegValues(void)
  179. {
  180. HKEY HCL = HKEY_CLASSES_ROOT; /* save typing! */
  181. /* Now just check that the OLE2 class ID is correct
  182. */
  183. if( !CheckRegValue( HCL, szMPlayer_CLSID, szMPOLE2GUID ) )
  184. return FALSE;
  185. /* Running the old MPlayer on Chicago also screws up the
  186. * file-extension associations, so make sure they haven't changed:
  187. */
  188. if( !CheckRegValue( HCL, aszKeyAVI, szAviFile ) )
  189. return FALSE;
  190. return TRUE;
  191. } /* CheckRegValues */
  192. /* start this thread to get the registry checked out.
  193. hwnd is typed as a LPVOID because that's what CreateThread wants.
  194. */
  195. DWORD WINAPI RegCheckThread(LPVOID hwnd)
  196. {
  197. if (!CheckRegValues())
  198. PostMessage((HWND)hwnd, WM_BADREG, 0, 0);
  199. return 0; /* end of thread! */
  200. }
  201. /* Call this with the hwnd that you want a WM_BADREG message posted to
  202. It will check the registry. No news is good news.
  203. It does the work on a separate thread, so this should return quickly.
  204. */
  205. void BackgroundRegCheck(HWND hwnd)
  206. {
  207. HANDLE hThread;
  208. DWORD thid;
  209. hThread = CreateThread( NULL /* no special security */
  210. , 0 /* default stack size */
  211. , RegCheckThread
  212. , (LPVOID)hwnd
  213. , 0 /* start running at once */
  214. , &thid
  215. );
  216. if (hThread!=NULL) CloseHandle(hThread); /* we don't need this any more */
  217. /* Else we're in some sort of trouble - dunno what to do.
  218. Can't think of an intelligible message to give to the user.
  219. Too bad. Creep home quietly.
  220. */
  221. } /* BackgroundRegCheck */
  222. /* returns TRUE if it worked. Dunno what to do if it didn't
  223. */
  224. BOOL SetRegValue(HKEY RootKey, LPTSTR KeyName, LPTSTR ValueName, LPTSTR ShouldBe)
  225. {
  226. HKEY hkey;
  227. if (ERROR_SUCCESS!=RegOpenKeyEx( RootKey
  228. , KeyName
  229. , 0 /* reserved */
  230. , KEY_SET_VALUE
  231. , &hkey
  232. )
  233. ) {
  234. /* Maybe the key has been DELETED - we've seen that */
  235. DWORD dwDisp;
  236. if (ERROR_SUCCESS!=RegCreateKeyEx( RootKey
  237. , KeyName
  238. , 0 /* reserved */
  239. , TEXT("") /* class */
  240. , REG_OPTION_NON_VOLATILE
  241. , KEY_SET_VALUE
  242. , NULL /* SecurityAttributes */
  243. , &hkey
  244. , &dwDisp
  245. )
  246. ) /* well we're really in trouble */
  247. return FALSE;
  248. else /* So now it exists, but we now have to open it */
  249. if (ERROR_SUCCESS!=RegOpenKeyEx( RootKey
  250. , KeyName
  251. , 0 /* reserved */
  252. , KEY_SET_VALUE
  253. , &hkey
  254. )
  255. ) /* Give up */
  256. return FALSE;
  257. }
  258. if (ERROR_SUCCESS!=RegSetValueEx( hkey
  259. , ValueName
  260. , 0 /* reserved */
  261. , REG_SZ
  262. , (LPBYTE)ShouldBe
  263. , (lstrlen(ShouldBe)+1)*sizeof(TCHAR) /* BYTES */
  264. )
  265. )
  266. return FALSE; /* couldn't set it */
  267. if ( ERROR_SUCCESS!=RegCloseKey(hkey) )
  268. /* no idea what to do!*/ ; /* couldn't set it */
  269. /* I'm NOT calling RegFlushKey. They'll get there eventually */
  270. return TRUE;
  271. } /* SetRegValue */
  272. /* Update the registry with the correct values. Return TRUE if everything succeeds */
  273. BOOL SetRegValues(void)
  274. {
  275. HKEY HCL = HKEY_CLASSES_ROOT; /* save typing! */
  276. DWORD i;
  277. #ifdef CHICAGO_PRODUCT
  278. TCHAR Buffer[MAX_PATH+40];
  279. #endif
  280. if( !( LOADSTRING( IDS_CLASSROOT, szMediaClip )
  281. && LOADSTRING( IDS_PLAYVERB, sz_Play )
  282. && LOADSTRING( IDS_EDITVERB, sz_Edit ) ) )
  283. /* If any of the strings fails to load, forget it:
  284. */
  285. return TRUE;
  286. #ifdef CHICAGO_PRODUCT
  287. if (pWindowsDirectory == NULL)
  288. {
  289. if ((pWindowsDirectory = AllocWindowsDirectory()) == NULL)
  290. return TRUE;
  291. }
  292. #endif
  293. for( i = 0; i < ( sizeof RegValues / sizeof *RegValues ); i+=2 )
  294. {
  295. /* Do a check to see whether this one needs changing,
  296. * to avoid gratuitous changes, and to avoid the slim chance
  297. * that an unnecessary SetRegValue might fail:
  298. */
  299. #ifdef CHICAGO_PRODUCT
  300. /* Do substitution of Windows directory, if required.
  301. * This simply copies the value to the buffer unchanged
  302. * if it doesn't contain a replacement character.
  303. */
  304. wsprintf(Buffer, RegValues[i+1], pWindowsDirectory);
  305. if( !CheckRegValue( HCL, RegValues[i], Buffer ) )
  306. #else
  307. if( !CheckRegValue( HCL, RegValues[i], RegValues[i+1] ) )
  308. #endif
  309. {
  310. #ifdef CHICAGO_PRODUCT
  311. DPF("Fixing the registry: Value - %"DTS"; Data - %"DTS"\n", RegValues[i], Buffer);
  312. if( !SetRegValue( HCL, RegValues[i], NULL, Buffer ) )
  313. #else
  314. DPF("Fixing the registry: Value - %"DTS"; Data - %"DTS"\n", RegValues[i], RegValues[i+1]);
  315. if( !SetRegValue( HCL, RegValues[i], NULL, RegValues[i+1] ) )
  316. #endif
  317. return FALSE;
  318. }
  319. }
  320. #ifdef CHICAGO_PRODUCT
  321. FreeStr (pWindowsDirectory);
  322. #endif
  323. return TRUE;
  324. } /* SetRegValues */
  325. BOOL IgnoreRegCheck()
  326. {
  327. DWORD fIgnore = 0L;
  328. ReadRegistryData(aszOptionsSection
  329. , aszIgnoreRegistryCheck
  330. , NULL
  331. , (LPBYTE)&fIgnore
  332. , sizeof fIgnore);
  333. return (fIgnore != 0L);
  334. } /* IgnoreRegCheck */
  335.