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.

359 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. extprog.c
  5. Abstract:
  6. Routines for invoking external applications.
  7. Entry points in this module:
  8. InvokeExternalApplication
  9. InvokeControlPanelApplet
  10. Author:
  11. Ted Miller (tedm) 5-Apr-1995
  12. Revision History:
  13. --*/
  14. #include "setupp.h"
  15. #pragma hdrstop
  16. PCWSTR szWaitOnApp = L"WaitOnApp";
  17. DWORD
  18. WaitOnApp(
  19. IN HANDLE Process,
  20. OUT PDWORD ExitCode,
  21. IN DWORD Timeout
  22. )
  23. {
  24. DWORD dw;
  25. BOOL Done;
  26. MYASSERT( ExitCode != NULL );
  27. //
  28. // Process any messages that may already be in the queue.
  29. //
  30. PumpMessageQueue();
  31. //
  32. // Wait for process to terminate or more messages in the queue.
  33. //
  34. Done = FALSE;
  35. do {
  36. switch(MsgWaitForMultipleObjects(1,&Process,FALSE,Timeout,QS_ALLINPUT)) {
  37. case WAIT_OBJECT_0:
  38. //
  39. // Process has terminated.
  40. //
  41. dw = GetExitCodeProcess(Process,ExitCode) ? NO_ERROR : GetLastError();
  42. Done = TRUE;
  43. break;
  44. case WAIT_OBJECT_0+1:
  45. //
  46. // Messages in the queue.
  47. //
  48. PumpMessageQueue();
  49. break;
  50. case WAIT_TIMEOUT:
  51. dw = WAIT_TIMEOUT;
  52. *ExitCode = WAIT_TIMEOUT;
  53. Done = TRUE;
  54. break;
  55. default:
  56. //
  57. // Error.
  58. //
  59. dw = GetLastError();
  60. Done = TRUE;
  61. break;
  62. }
  63. } while(!Done);
  64. return(dw);
  65. }
  66. BOOL
  67. InvokeExternalApplication(
  68. IN PCWSTR ApplicationName, OPTIONAL
  69. IN PCWSTR CommandLine,
  70. IN OUT PDWORD ExitCode OPTIONAL
  71. )
  72. /*++
  73. Routine Description:
  74. See InvokeExternalApplicationEx
  75. --*/
  76. {
  77. //
  78. // infinite timeout
  79. //
  80. return(InvokeExternalApplicationEx(
  81. ApplicationName,
  82. CommandLine,
  83. ExitCode,
  84. INFINITE,
  85. FALSE));
  86. }
  87. BOOL
  88. InvokeExternalApplicationEx(
  89. IN PCWSTR ApplicationName, OPTIONAL
  90. IN PCWSTR CommandLine,
  91. IN OUT PDWORD ExitCode, OPTIONAL
  92. IN DWORD Timeout,
  93. IN BOOL Hidden
  94. )
  95. /*++
  96. Routine Description:
  97. Invokes an external program, which is optionally detached.
  98. Arguments:
  99. ApplicationName - supplies app name. May be a partial or full path,
  100. or just a filename, in which case the standard win32 path search
  101. is performed. If not specified then the first element in
  102. CommandLine must specify the binary to execute.
  103. CommandLine - supplies the command line to be passed to the
  104. application.
  105. ExitCode - If specified, the execution is synchronous and this value
  106. receives the exit code of the application. If not specified,
  107. the execution is asynchronous.
  108. Timeout - specifies how long to wait for the app to complete.
  109. Hidden - if TRUE, indicates that the application should be invoked with
  110. the SW_HIDE attribute set.
  111. Return Value:
  112. Boolean value indicating whether the process was started successfully.
  113. --*/
  114. {
  115. PWSTR FullCommandLine;
  116. BOOL b;
  117. PROCESS_INFORMATION ProcessInfo;
  118. STARTUPINFO StartupInfo;
  119. DWORD d;
  120. b = FALSE;
  121. //
  122. // Form the command line to be passed to CreateProcess.
  123. //
  124. if(ApplicationName) {
  125. FullCommandLine = MyMalloc((lstrlen(ApplicationName)+lstrlen(CommandLine)+2)*sizeof(WCHAR));
  126. if(!FullCommandLine) {
  127. SetuplogError(
  128. LogSevWarning,
  129. SETUPLOG_USE_MESSAGEID,
  130. MSG_LOG_INVOKEAPP_FAIL,
  131. ApplicationName,NULL,
  132. SETUPLOG_USE_MESSAGEID,
  133. MSG_LOG_OUTOFMEMORY,
  134. NULL,NULL);
  135. goto err0;
  136. }
  137. lstrcpy(FullCommandLine,ApplicationName);
  138. lstrcat(FullCommandLine,L" ");
  139. lstrcat(FullCommandLine,CommandLine);
  140. } else {
  141. FullCommandLine = pSetupDuplicateString(CommandLine);
  142. if(!FullCommandLine) {
  143. SetuplogError(
  144. LogSevWarning,
  145. SETUPLOG_USE_MESSAGEID,
  146. MSG_LOG_INVOKEAPP_FAIL,
  147. CommandLine, NULL,
  148. SETUPLOG_USE_MESSAGEID,
  149. MSG_LOG_OUTOFMEMORY,
  150. NULL,NULL);
  151. goto err0;
  152. }
  153. }
  154. //
  155. // Initialize startup info.
  156. //
  157. ZeroMemory(&StartupInfo,sizeof(STARTUPINFO));
  158. StartupInfo.cb = sizeof(STARTUPINFO);
  159. if (Hidden) {
  160. //
  161. // no UI
  162. //
  163. GetStartupInfo(&StartupInfo);
  164. StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
  165. StartupInfo.wShowWindow = SW_HIDE;
  166. }
  167. //
  168. // Create the process.
  169. //
  170. b = CreateProcess(
  171. NULL,
  172. FullCommandLine,
  173. NULL,
  174. NULL,
  175. FALSE,
  176. ExitCode ? 0 : DETACHED_PROCESS,
  177. NULL,
  178. NULL,
  179. &StartupInfo,
  180. &ProcessInfo
  181. );
  182. if(!b) {
  183. SetuplogError(
  184. LogSevWarning,
  185. SETUPLOG_USE_MESSAGEID,
  186. MSG_LOG_INVOKEAPP_FAIL,
  187. FullCommandLine, NULL,
  188. SETUPLOG_USE_MESSAGEID,
  189. MSG_LOG_X_RETURNED_WINERR,
  190. szCreateProcess,
  191. GetLastError(),
  192. NULL,NULL);
  193. goto err1;
  194. }
  195. //
  196. // If execution is asynchronus, we're done.
  197. //
  198. if(!ExitCode) {
  199. SetuplogError(
  200. LogSevInformation,
  201. SETUPLOG_USE_MESSAGEID,
  202. MSG_LOG_INVOKEAPP_SUCCEED,
  203. FullCommandLine,
  204. NULL,NULL);
  205. goto err2;
  206. }
  207. //
  208. // Need to wait for the app to finish.
  209. // If the wait failed don't return an error but log a warning.
  210. //
  211. d = WaitOnApp(ProcessInfo.hProcess,ExitCode,Timeout);
  212. if(d != NO_ERROR) {
  213. SetuplogError(
  214. LogSevWarning,
  215. SETUPLOG_USE_MESSAGEID,
  216. MSG_LOG_INVOKEAPP_FAIL,
  217. FullCommandLine, 0,
  218. SETUPLOG_USE_MESSAGEID,
  219. MSG_LOG_X_RETURNED_WINERR,
  220. szWaitOnApp,
  221. d,
  222. NULL,NULL);
  223. } else {
  224. SetuplogError(
  225. LogSevInformation | SETUPLOG_SINGLE_MESSAGE,
  226. SETUPLOG_USE_MESSAGEID,
  227. MSG_LOG_INVOKEAPP_SUCCEED_STATUS,
  228. FullCommandLine,
  229. *ExitCode,
  230. NULL,
  231. NULL);
  232. }
  233. //
  234. // Put setup back in the foreground.
  235. //
  236. SetForegroundWindow(MainWindowHandle);
  237. err2:
  238. CloseHandle(ProcessInfo.hThread);
  239. CloseHandle(ProcessInfo.hProcess);
  240. err1:
  241. MyFree(FullCommandLine);
  242. err0:
  243. return(b);
  244. }
  245. BOOL
  246. InvokeControlPanelApplet(
  247. IN PCWSTR CplSpec,
  248. IN PCWSTR AppletName, OPTIONAL
  249. IN UINT AppletNameStringId,
  250. IN PCWSTR CommandLine
  251. )
  252. {
  253. PWSTR FullCommandLine;
  254. BOOL b;
  255. BOOL LoadedAppletName;
  256. DWORD ExitCode;
  257. b = FALSE;
  258. LoadedAppletName = FALSE;
  259. if(!AppletName) {
  260. if(AppletName = MyLoadString(AppletNameStringId)) {
  261. LoadedAppletName = TRUE;
  262. }
  263. }
  264. if(AppletName) {
  265. FullCommandLine = MyMalloc((lstrlen(CplSpec)+lstrlen(AppletName)+lstrlen(CommandLine)+3) * sizeof(WCHAR));
  266. if(FullCommandLine) {
  267. lstrcpy(FullCommandLine,CplSpec);
  268. lstrcat(FullCommandLine,L",");
  269. lstrcat(FullCommandLine,AppletName);
  270. lstrcat(FullCommandLine,L",");
  271. lstrcat(FullCommandLine,CommandLine);
  272. b = InvokeExternalApplication(L"RUNDLL32 shell32,Control_RunDLL",FullCommandLine,&ExitCode);
  273. MyFree(FullCommandLine);
  274. } else {
  275. SetuplogError(
  276. LogSevWarning,
  277. SETUPLOG_USE_MESSAGEID,
  278. MSG_LOG_INVOKEAPPLET_FAIL,
  279. AppletName, NULL,
  280. SETUPLOG_USE_MESSAGEID,
  281. MSG_LOG_OUTOFMEMORY,
  282. NULL,NULL);
  283. }
  284. } else {
  285. SetuplogError(
  286. LogSevWarning,
  287. SETUPLOG_USE_MESSAGEID,
  288. MSG_LOG_INVOKEAPPLET_FAIL,
  289. L"", NULL,
  290. SETUPLOG_USE_MESSAGEID,
  291. MSG_LOG_OUTOFMEMORY,
  292. NULL,NULL);
  293. }
  294. if(LoadedAppletName) {
  295. MyFree(AppletName);
  296. }
  297. return(b);
  298. }