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.

381 lines
9.1 KiB

  1. /*
  2. * SETUPDD.CPP
  3. *
  4. * The code to install the NM display driver for Windows NT. This was
  5. * a standalone application launched by Setup that we are now importing
  6. * into NM itself.
  7. *
  8. * Author:
  9. * dannygl, 05 Apr 97
  10. */
  11. #include "precomp.h"
  12. #include "conf.h"
  13. #include "confwnd.h"
  14. #include "resource.h"
  15. #include "setupdd.h"
  16. // String to identify the DLL and function that we need to call to install
  17. // the display driver on SP3.
  18. const TCHAR g_pcszDisplayCPLName[] = TEXT("DESK.CPL");
  19. const CHAR g_pcszInstallDriverAPIName[] = "InstallGraphicsDriver";
  20. const WCHAR g_pcwszDefaultModelName[] = L"Microsoft NetMeeting graphics driver";
  21. const WCHAR g_pcwszDefaultINFName[] = L"MNMDD.INF";
  22. // Maxmimum size of the model name string
  23. const int NAME_BUFFER_SIZE = 128;
  24. // Prototype for the function installed by the Display CPL
  25. typedef DWORD (*PFNINSTALLGRAPHICSDRIVER)(
  26. HWND hwnd,
  27. LPCWSTR pszSourceDirectory,
  28. LPCWSTR pszModel,
  29. LPCWSTR pszInf
  30. );
  31. /*
  32. * GetInstallDisplayDriverEntryPoint
  33. *
  34. * This function loads the DLL containing the display driver installation
  35. * code and retrieves the entry point for the installation function. It
  36. * is used by the below functions as a utility function.
  37. *
  38. * It returns TRUE if it is able to load the library and get the entry point,
  39. * FALSE if either operation fails. It is returns TRUE, it also returns the
  40. * DLL module handle and the function address.
  41. */
  42. BOOL
  43. GetInstallDisplayDriverEntryPoint(
  44. HMODULE *phInstallDDDll,
  45. PFNINSTALLGRAPHICSDRIVER *ppfnInstallDDFunction)
  46. {
  47. HMODULE hDll;
  48. PFNINSTALLGRAPHICSDRIVER pfn = NULL;
  49. ASSERT(NULL != phInstallDDDll
  50. && NULL != ppfnInstallDDFunction);
  51. hDll = NmLoadLibrary(g_pcszDisplayCPLName,TRUE);
  52. if (NULL != hDll)
  53. {
  54. pfn = (PFNINSTALLGRAPHICSDRIVER)
  55. GetProcAddress(hDll,
  56. g_pcszInstallDriverAPIName);
  57. }
  58. // If the entry point exists, we pass it and the DLL handle back to
  59. // the caller. Otherwise, we unload the DLL immediately.
  60. if (NULL != pfn)
  61. {
  62. *phInstallDDDll = hDll;
  63. *ppfnInstallDDFunction = pfn;
  64. return TRUE;
  65. }
  66. else
  67. {
  68. if (NULL != hDll)
  69. {
  70. FreeLibrary(hDll);
  71. }
  72. return FALSE;
  73. }
  74. }
  75. /*
  76. * CanInstallNTDisplayDriver
  77. *
  78. * This function determines whether the entry point for installing the
  79. * NT display driver is availalble (i.e. NT 4.0 SP3 or later).
  80. */
  81. BOOL
  82. CanInstallNTDisplayDriver(void)
  83. {
  84. static BOOL fComputed = FALSE;
  85. static BOOL fRet = FALSE;
  86. ASSERT(::IsWindowsNT());
  87. // We verify that the major version number is exactly 4 and either
  88. // the minor version number is greater than 0 or the service pack
  89. // number (which is stored in the high byte of the low word of the
  90. // CSD version) is 3 or greater.
  91. if (! fComputed)
  92. {
  93. LPOSVERSIONINFO lposvi = GetVersionInfo();
  94. if (4 == lposvi->dwMajorVersion)
  95. {
  96. if (0 == lposvi->dwMinorVersion)
  97. {
  98. RegEntry re(NT_WINDOWS_SYSTEM_INFO_KEY, HKEY_LOCAL_MACHINE, FALSE);
  99. DWORD dwCSDVersion =
  100. re.GetNumber(REGVAL_NT_CSD_VERSION, 0);
  101. if (3 <= HIBYTE(LOWORD(dwCSDVersion)))
  102. {
  103. // This is NT 4.0, SP 3 or later
  104. fRet = TRUE;
  105. }
  106. }
  107. else
  108. {
  109. // We assume that any future version of Windows NT 4.x (x > 0)
  110. // will support this.
  111. fRet = TRUE;
  112. }
  113. }
  114. fComputed = TRUE;
  115. }
  116. ASSERT(fComputed);
  117. return fRet;
  118. }
  119. /*
  120. * OnEnableAppSharing
  121. *
  122. * Invoked when the "Enable Application Sharing" menu item is selected.
  123. *
  124. * This function determines whether the entry point for installing the
  125. * NT display driver is available. If so, it prompts the user to confirm
  126. * this operation, proceeds with the installation, and then prompts the
  127. * user to restart the computer.
  128. *
  129. * If not, it presents a text dialog with information about how to get
  130. * the necessary NT Service Pack(s).
  131. */
  132. void
  133. OnEnableAppSharing(
  134. HWND hWnd)
  135. {
  136. ASSERT(::IsWindowsNT());
  137. BSTR pwszSourcePath =NULL;
  138. if (::CanInstallNTDisplayDriver())
  139. {
  140. // Confirm the installation with the user
  141. if (IDYES == ::ConfMsgBox(
  142. hWnd,
  143. (LPCTSTR) IDS_ENABLEAPPSHARING_INSTALL_CONFIRM,
  144. MB_YESNO | MB_ICONQUESTION))
  145. {
  146. BOOL fDriverInstallSucceeded = FALSE;
  147. HMODULE hDisplayCPL = NULL;
  148. PFNINSTALLGRAPHICSDRIVER pfnInstallGraphicsDriver;
  149. TCHAR pszSourcePath[MAX_PATH];
  150. LPWSTR pwszSourcePathEnd;
  151. WCHAR pwszModelNameBuffer[NAME_BUFFER_SIZE];
  152. LPCWSTR pcwszModelName;
  153. WCHAR pwszINFNameBuffer[MAX_PATH];
  154. LPCWSTR pcwszINFName;
  155. // Get the entry point for display driver installation
  156. if (! ::GetInstallDisplayDriverEntryPoint(
  157. &hDisplayCPL,
  158. &pfnInstallGraphicsDriver))
  159. {
  160. ERROR_OUT(("GetInstallDisplayDriverEntryPoint() fails"));
  161. goto OEAS_AbortInstall;
  162. }
  163. // The driver files are located in the NM directory.
  164. if (! ::GetInstallDirectory(pszSourcePath))
  165. {
  166. ERROR_OUT(("GetInstallDirectory() fails"));
  167. goto OEAS_AbortInstall;
  168. }
  169. // Always write display name in UNICODE
  170. if(FAILED(LPTSTR_to_BSTR(&pwszSourcePath, pszSourcePath)))
  171. {
  172. goto OEAS_AbortInstall;
  173. }
  174. if (NULL == pwszSourcePath)
  175. {
  176. ERROR_OUT(("AnsiToUnicode() fails"));
  177. goto OEAS_AbortInstall;
  178. }
  179. // Strip the trailing backslash that GetInstallDirectory appends
  180. pwszSourcePathEnd = (LPWSTR)pwszSourcePath + lstrlenW((LPWSTR)pwszSourcePath);
  181. // Handle X:\, just to be safe
  182. if (pwszSourcePathEnd - (LPWSTR)pwszSourcePath > 3)
  183. {
  184. ASSERT(L'\\' == *(pwszSourcePathEnd - 1));
  185. *--pwszSourcePathEnd = L'\0';
  186. }
  187. // Read the model name string from the resource file
  188. if (0 < ::LoadStringW(GetInstanceHandle(),
  189. IDS_NMDD_DISPLAYNAME,
  190. pwszModelNameBuffer,
  191. CCHMAX(pwszModelNameBuffer)))
  192. {
  193. pcwszModelName = pwszModelNameBuffer;
  194. }
  195. else
  196. {
  197. ERROR_OUT(("LoadStringW() fails, err=%lu", GetLastError()));
  198. pcwszModelName = g_pcwszDefaultModelName;
  199. }
  200. // Read the INF name string from the resource file
  201. if (0 < ::LoadStringW(GetInstanceHandle(),
  202. IDS_NMDD_INFNAME,
  203. pwszINFNameBuffer,
  204. CCHMAX(pwszINFNameBuffer)))
  205. {
  206. pcwszINFName = pwszINFNameBuffer;
  207. }
  208. else
  209. {
  210. ERROR_OUT(("LoadStringW() fails, err=%lu", GetLastError()));
  211. pcwszINFName = g_pcwszDefaultINFName;
  212. }
  213. // Now we're set to call the actual installation function
  214. DWORD dwErr;
  215. dwErr = (*pfnInstallGraphicsDriver)(hWnd,
  216. (LPWSTR)pwszSourcePath,
  217. pcwszModelName,
  218. pcwszINFName);
  219. if (dwErr)
  220. {
  221. WARNING_OUT(("InstallGraphicsDriver() fails, err=%lu", dwErr));
  222. }
  223. if (ERROR_SUCCESS == dwErr)
  224. {
  225. fDriverInstallSucceeded = TRUE;
  226. g_fNTDisplayDriverEnabled = TRUE;
  227. }
  228. OEAS_AbortInstall:
  229. SysFreeString(pwszSourcePath);
  230. // If we failed to install the driver, we report an error.
  231. // If we succeeded, we prompt the user to restart the system.
  232. if (! fDriverInstallSucceeded)
  233. {
  234. ::ConfMsgBox(
  235. hWnd,
  236. (LPCTSTR) IDS_ENABLEAPPSHARING_INSTALL_FAILURE,
  237. MB_OK | MB_ICONERROR);
  238. }
  239. else if (IDYES == ::ConfMsgBox(
  240. hWnd,
  241. (LPCTSTR) IDS_ENABLEAPPSHARING_INSTALL_COMPLETE,
  242. MB_YESNO | MB_ICONQUESTION))
  243. {
  244. // Initiate a system restart. This involves getting the
  245. // necessary privileges first.
  246. HANDLE hToken;
  247. TOKEN_PRIVILEGES tkp;
  248. BOOL fRet;
  249. // Get the current process token handle so we can get shutdown
  250. // privilege.
  251. fRet = OpenProcessToken(
  252. GetCurrentProcess(),
  253. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  254. &hToken);
  255. // Get the LUID for shutdown privilege.
  256. if (fRet)
  257. {
  258. fRet = LookupPrivilegeValue(
  259. NULL,
  260. SE_SHUTDOWN_NAME,
  261. &tkp.Privileges[0].Luid);
  262. }
  263. else
  264. {
  265. hToken = NULL;
  266. WARNING_OUT(("OpenProcessToken() fails (error %lu)", GetLastError()));
  267. }
  268. // Get shutdown privilege for this process.
  269. if (fRet)
  270. {
  271. tkp.PrivilegeCount = 1;
  272. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  273. fRet = AdjustTokenPrivileges(
  274. hToken,
  275. FALSE,
  276. &tkp,
  277. 0,
  278. (PTOKEN_PRIVILEGES) NULL,
  279. 0);
  280. // Special-case scenario where call succeeds but not all
  281. // privileges were set.
  282. if (fRet && ERROR_SUCCESS != GetLastError())
  283. {
  284. fRet = FALSE;
  285. }
  286. }
  287. else
  288. {
  289. WARNING_OUT(("LookupPrivilegeValue() fails (error %lu)", GetLastError()));
  290. }
  291. if (! fRet)
  292. {
  293. WARNING_OUT(("AdjustTokenPrivileges() fails (error %lu)", GetLastError()));
  294. }
  295. if (NULL != hToken)
  296. {
  297. CloseHandle(hToken);
  298. }
  299. if (! ::ExitWindowsEx(EWX_REBOOT, 0))
  300. {
  301. WARNING_OUT(("ExitWindowsEx() fails (error %lu)", GetLastError()));
  302. }
  303. }
  304. if (NULL != hDisplayCPL)
  305. {
  306. FreeLibrary(hDisplayCPL);
  307. }
  308. }
  309. }
  310. else
  311. {
  312. // Tell the user how to get the SP
  313. ::ConfMsgBox(
  314. hWnd,
  315. (LPCTSTR) IDS_ENABLEAPPSHARING_NEEDNTSP);
  316. }
  317. return;
  318. }