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.

1279 lines
39 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: ActList.cpp
  4. //
  5. // Module: CMDIAL32.DLL
  6. //
  7. // Synopsis: Implement the two connect action list class
  8. // CAction and CActionList
  9. //
  10. // Copyright (c) 1997-1999 Microsoft Corporation
  11. //
  12. // Author: fengsun Created 11/14/97
  13. //
  14. //+----------------------------------------------------------------------------
  15. #include "cmmaster.h"
  16. #include "ActList.h"
  17. #include "stp_str.h"
  18. //
  19. // Include the custom action parsing routine that CM and CMAK now share, HrParseCustomActionString
  20. //
  21. #include "parseca.cpp"
  22. //
  23. // Constructor and destructor
  24. //
  25. CActionList::CActionList()
  26. {
  27. m_pActionList = NULL;
  28. m_nNum = 0;
  29. m_nSize = 0;
  30. m_pszType = NULL;
  31. }
  32. CActionList::~CActionList()
  33. {
  34. for (UINT i = 0; i < m_nNum; i++)
  35. {
  36. delete m_pActionList[i];
  37. }
  38. CmFree(m_pActionList);
  39. }
  40. //+----------------------------------------------------------------------------
  41. //
  42. // Function: CActionList::Add
  43. //
  44. // Synopsis: Dynamic array function. Append the element at the end of the array
  45. // Grow the array if nessesary
  46. //
  47. // Arguments: CAction* pAction - element to be added
  48. //
  49. // Returns: Nothing
  50. //
  51. // History: Fengsun Created Header 11/14/97
  52. // tomkel Fixed PREFIX issues 11/21/2000
  53. //
  54. //+----------------------------------------------------------------------------
  55. void CActionList::Add(CAction* pAction)
  56. {
  57. MYDBGASSERT(m_nNum <= m_nSize);
  58. MYDBGASSERT(m_nSize == 0 || m_pActionList!=NULL); // if (m_nSize!=0) ASSERT(m_pActionList!=NULL);
  59. m_nNum++;
  60. if (m_nNum > m_nSize)
  61. {
  62. //
  63. // Either there is not enough room OR m_pActionList is NULL (this
  64. // is the first call to Add). Need to allocate memory
  65. //
  66. CAction** pNewList = (CAction**)CmMalloc((m_nSize + GROW_BY)*sizeof(CAction*));
  67. MYDBGASSERT(pNewList);
  68. if (m_pActionList && pNewList)
  69. {
  70. //
  71. // Memory was allocated and there is something to copy from m_pActionList
  72. //
  73. CopyMemory(pNewList, m_pActionList, (m_nSize)*sizeof(CAction*));
  74. }
  75. if (pNewList)
  76. {
  77. //
  78. // Memory was allocated
  79. //
  80. CmFree(m_pActionList);
  81. m_pActionList = pNewList;
  82. m_nSize += GROW_BY;
  83. //
  84. // Add the action
  85. //
  86. m_pActionList[m_nNum - 1] = pAction;
  87. }
  88. else
  89. {
  90. //
  91. // Memory was not allocated, so Add did not happen
  92. // Need to decrement the number of items in list (m_nNum)
  93. // since it was inceremented at the beginning.
  94. //
  95. m_nNum--;
  96. }
  97. }
  98. else
  99. {
  100. //
  101. // Just add the action to the end
  102. //
  103. m_pActionList[m_nNum - 1] = pAction;
  104. }
  105. }
  106. //+----------------------------------------------------------------------------
  107. //
  108. // Function: CActionList::GetAt
  109. //
  110. // Synopsis: Dynamic array fuction. Get the element at nIndex
  111. //
  112. // Arguments: UINT nIndex -
  113. //
  114. // Returns: inline CAction* -
  115. //
  116. // History: fengsun Created Header 11/14/97
  117. //
  118. //+----------------------------------------------------------------------------
  119. inline CAction* CActionList::GetAt(UINT nIndex)
  120. {
  121. MYDBGASSERT(nIndex<m_nNum);
  122. MYDBGASSERT(m_pActionList);
  123. MYDBGASSERT(m_nNum <= m_nSize);
  124. return m_pActionList[nIndex];
  125. }
  126. //+----------------------------------------------------------------------------
  127. //
  128. // Function: CActionList::Append
  129. //
  130. // Synopsis: Append new actions to the list from profile
  131. //
  132. // Arguments: const CIni* piniService - The service file containing actions information
  133. // LPCTSTR pszSection - The section name
  134. //
  135. // Returns: TRUE if an action was appended to the list
  136. //
  137. // History: fengsun Created Header 11/14/97
  138. // nickball Removed current directory assumptions, and added piniProfile
  139. // nickball Added Return code 03/22/99
  140. //
  141. //+----------------------------------------------------------------------------
  142. BOOL CActionList::Append(const CIni* piniService, LPCTSTR pszSection)
  143. {
  144. MYDBGASSERT(piniService);
  145. BOOL bRet = FALSE;
  146. //
  147. // Read each of the entries and add to our list
  148. // Start from 0 till the first empty entry
  149. //
  150. for (DWORD dwIdx=0; ; dwIdx++)
  151. {
  152. TCHAR szEntry[32]; // hold the entry name
  153. wsprintfU(szEntry, TEXT("%u"), dwIdx);
  154. LPTSTR pszCmd = piniService->GPPS(pszSection, szEntry); // Command line
  155. if (*pszCmd == TEXT('\0'))
  156. {
  157. //
  158. // No more entries
  159. //
  160. CmFree(pszCmd);
  161. break;
  162. }
  163. //
  164. // Read the flag
  165. //
  166. UINT iFlag = 0;
  167. if (pszSection && pszSection[0])
  168. {
  169. wsprintfU(szEntry, c_pszCmEntryConactFlags, dwIdx); //0&Flags
  170. iFlag = (UINT)piniService->GPPI(pszSection, szEntry, 0);
  171. }
  172. //
  173. // Read the description
  174. //
  175. LPTSTR pszDescript = NULL;
  176. wsprintfU(szEntry, c_pszCmEntryConactDesc, dwIdx); //0&Description
  177. pszDescript = piniService->GPPS(pszSection, szEntry);
  178. //
  179. // CAction is responsible for releasing pszDescript
  180. //
  181. CAction* pAction = new CAction(pszCmd, iFlag, pszDescript);
  182. CmFree(pszCmd);
  183. if (pAction)
  184. {
  185. pAction->ConvertRelativePath(piniService);
  186. ASSERT_VALID(pAction);
  187. pAction->ExpandEnvironmentStringsInCommand();
  188. Add(pAction);
  189. bRet = TRUE;
  190. }
  191. }
  192. if (bRet)
  193. {
  194. m_pszType = pszSection;
  195. }
  196. return bRet;
  197. }
  198. //+----------------------------------------------------------------------------
  199. //
  200. // Function: CActionList::RunAccordType
  201. //
  202. // Synopsis: Run the action list according to the connection type
  203. //
  204. // Arguments: HWND hwndDlg - The parent window
  205. // _ArgsStruct *pArgs -
  206. // BOOL fStatusMsgOnFailure - Whether to display a status message
  207. // to the user in the event of failure
  208. // BOOL fOnError - are we running OnError connect action?
  209. //
  210. // Returns: BOOL - FALSE, if some sync action failed to start or returns failed
  211. //
  212. // History: Fengsun Created Header 12/5/97
  213. //
  214. //+----------------------------------------------------------------------------
  215. BOOL CActionList::RunAccordType(HWND hwndDlg, _ArgsStruct *pArgs, BOOL fStatusMsgOnFailure, BOOL fOnError)
  216. {
  217. //
  218. // Set the flag, so CM will not handle WM_TIMER and RAS messages
  219. //
  220. pArgs->fIgnoreTimerRasMsg = TRUE;
  221. BOOL fRetValue = Run(hwndDlg, pArgs, FALSE, fStatusMsgOnFailure, fOnError);//fAddWatch = FALSE
  222. pArgs->fIgnoreTimerRasMsg = FALSE;
  223. return fRetValue;
  224. }
  225. //+----------------------------------------------------------------------------
  226. //
  227. // Function: CActionList::Run
  228. //
  229. // Synopsis: Run the action list
  230. //
  231. // Arguments: HWND hwndDlg - The parent window, which is diabled during the process
  232. // ArgsStruct *pArgs -
  233. // BOOL fAddWatch - If true, will add the process as watch process,
  234. // BOOL fStatusMsgOnFailure - Whether to display a status message
  235. // to the user in the event of failure
  236. // BOOL fOnError - are we running OnError connect action?
  237. //
  238. // Returns: BOOL - FALSE, if some sync action failed to start or returns failed
  239. //
  240. // History: fengsun Created Header 11/14/97
  241. //
  242. //+----------------------------------------------------------------------------
  243. BOOL CActionList::Run(HWND hwndDlg, ArgsStruct *pArgs, BOOL fAddWatch, BOOL fStatusMsgOnFailure, BOOL fOnError)
  244. {
  245. //
  246. // Disable the window, and enable it on return
  247. //
  248. CFreezeWindow FreezeWindow(hwndDlg);
  249. for (UINT i = 0; i < GetSize(); i++)
  250. {
  251. CAction* pAction = (CAction*)GetAt(i);
  252. DWORD dwLoadType = (DWORD)-1;
  253. ASSERT_VALID(pAction);
  254. MYDBGASSERT(m_pszType);
  255. //
  256. // Lets check the flags value to see if this connect action should
  257. // run for this type of connection.
  258. //
  259. if (FALSE == pAction->RunConnectActionForCurrentConnection(pArgs))
  260. {
  261. continue;
  262. }
  263. //
  264. // Replace %xxxx% with the value
  265. //
  266. pAction->ExpandMacros(pArgs);
  267. //
  268. // Also expand any environment variables
  269. // NOTE: the order (macros vs. env vars) is deliberate. Macros get
  270. // expanded first.
  271. //
  272. pAction->ExpandEnvironmentStringsInParams();
  273. //
  274. // Check to see if we can run the action @ this moment
  275. //
  276. if (FALSE == pAction->IsAllowed(pArgs, &dwLoadType))
  277. {
  278. //
  279. // If not allowed, log the fact that we didn't run this connect action
  280. // and then just skip it.
  281. //
  282. pArgs->Log.Log(CUSTOMACTION_NOT_ALLOWED, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram());
  283. continue;
  284. }
  285. //
  286. // If this customaction might bring up UI
  287. //
  288. if (pAction->HasUI())
  289. {
  290. //
  291. // If we are in unattended mode, don't run any connect actions
  292. //
  293. if (pArgs->dwFlags & FL_UNATTENDED)
  294. {
  295. pArgs->Log.Log(CUSTOMACTION_NOT_ALLOWED, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram());
  296. CMTRACE(TEXT("Run: skipped past a customaction because we are in unattended mode"));
  297. continue;
  298. }
  299. //
  300. // Custom actions processed during a Fast User Switch can put up UI requiring
  301. // user input, effectively blocking CM.
  302. //
  303. if (pArgs->fInFastUserSwitch)
  304. {
  305. CMASSERTMSG((CM_CREDS_GLOBAL != pArgs->dwCurrentCredentialType),
  306. TEXT("CActionList::Run - in FUS disconnect, but connectoid has global creds!"));
  307. pArgs->Log.Log(CUSTOMACTION_NOT_ALLOWED, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram());
  308. CMTRACE(TEXT("Run: skipped past a singleuser DLL connectaction because of FUS"));
  309. continue;
  310. }
  311. }
  312. if (pAction->IsDll())
  313. {
  314. DWORD dwActionRetValue=0; // the connect action return value, in COM format
  315. BOOL bLoadSucceed = FALSE;
  316. if (hwndDlg)
  317. {
  318. //
  319. // Display description for DLL
  320. //
  321. if (pAction->GetDescription())
  322. {
  323. LPTSTR lpszText = CmFmtMsg(g_hInst, IDMSG_CONN_ACTION_RUNNING, pAction->GetDescription());
  324. //
  325. // Update the main dialog status window
  326. //
  327. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, lpszText);
  328. CmFree(lpszText);
  329. }
  330. }
  331. bLoadSucceed = pAction->RunAsDll(hwndDlg, dwActionRetValue, dwLoadType);
  332. if (bLoadSucceed)
  333. {
  334. pArgs->Log.Log(CUSTOMACTIONDLL, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()),
  335. pAction->GetProgram(), dwActionRetValue);
  336. }
  337. else
  338. {
  339. pArgs->Log.Log(CUSTOMACTION_WONT_RUN, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()),
  340. pAction->GetProgram());
  341. }
  342. //
  343. // Failed to start the action, or the action returned failure
  344. //
  345. if (FAILED(dwActionRetValue) || !bLoadSucceed)
  346. {
  347. LPTSTR lpszText = NULL;
  348. if (fStatusMsgOnFailure &&
  349. hwndDlg &&
  350. pAction->GetDescription())
  351. {
  352. if (bLoadSucceed)
  353. {
  354. lpszText = CmFmtMsg(g_hInst, IDMSG_CONN_ACTION_FAILED,
  355. pAction->GetDescription(), dwActionRetValue);
  356. }
  357. else
  358. {
  359. lpszText = CmFmtMsg(g_hInst, IDMSG_CONN_ACTION_NOTFOUND,
  360. pAction->GetDescription());
  361. }
  362. //
  363. // Update the main dialog status window
  364. //
  365. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, lpszText);
  366. }
  367. if (!fOnError)
  368. {
  369. DWORD dwError = 0;
  370. if (bLoadSucceed)
  371. {
  372. dwError = dwActionRetValue;
  373. }
  374. else
  375. {
  376. dwError = ERROR_DLL_NOT_FOUND;
  377. }
  378. pArgs->Log.Log(ONERROR_EVENT, dwError, pAction->GetDescription());
  379. //
  380. // We'll run On-Error connect actions if we are not already running OnError
  381. // connect action. This is to prevent infinite loops.
  382. //
  383. CActionList OnErrorActList;
  384. OnErrorActList.Append(pArgs->piniService, c_pszCmSectionOnError);
  385. //
  386. // fStatusMsgOnFailure = FALSE
  387. //
  388. OnErrorActList.RunAccordType(hwndDlg, pArgs, FALSE, TRUE);
  389. //
  390. // Update the program state
  391. //
  392. if (fStatusMsgOnFailure)
  393. {
  394. lstrcpynU(pArgs->szLastErrorSrc, pAction->GetDescription(), MAX_LASTERR_LEN);
  395. pArgs->dwExitCode = dwError;
  396. SetInteractive(pArgs->hwndMainDlg, pArgs);
  397. pArgs->psState = PS_Error;
  398. }
  399. }
  400. if (lpszText)
  401. {
  402. //
  403. // restore the failure msg of the previous connect action
  404. //
  405. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, lpszText);
  406. CmFree(lpszText);
  407. }
  408. //
  409. // Note that if a DLL connect action fails, we will stop processing connect actions.
  410. // If the fStatusMsgOnFailure flag is set, then we won't show an error message
  411. // but connect action processing will still halt (we do this in cases where the user
  412. // isn't going to care such as oncancel actions, onerror actions, and cases where
  413. // disconnect action fail).
  414. //
  415. return FALSE;
  416. }
  417. }
  418. else
  419. {
  420. HANDLE hProcess = NULL;
  421. TCHAR szDesktopName[MAX_PATH];
  422. TCHAR szWinDesktop[MAX_PATH];
  423. if (IsLogonAsSystem())
  424. {
  425. DWORD cb;
  426. HDESK hDesk = GetThreadDesktop(GetCurrentThreadId());
  427. //
  428. // Get the name of the desktop. Normally returns default or Winlogon or system or WinNT
  429. // On Win95/98 GetUserObjectInformation is not supported and thus the desktop name
  430. // will be empty so we will use the good old API
  431. //
  432. szDesktopName[0] = 0;
  433. if (hDesk && GetUserObjectInformation(hDesk, UOI_NAME, szDesktopName, sizeof(szDesktopName), &cb))
  434. {
  435. lstrcpyU(szWinDesktop, TEXT("Winsta0\\"));
  436. lstrcatU(szWinDesktop, szDesktopName);
  437. CMTRACE1(TEXT("CActionList::Run - Desktop = %s"), MYDBGSTR(szWinDesktop));
  438. hProcess = pAction->RunAsExeFromSystem(&pArgs->m_ShellDll, szWinDesktop, dwLoadType);
  439. if (NULL != hProcess)
  440. {
  441. pArgs->Log.Log(CUSTOMACTIONEXE, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram());
  442. }
  443. else
  444. {
  445. pArgs->Log.Log(CUSTOMACTION_WONT_RUN, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram());
  446. }
  447. }
  448. else
  449. {
  450. //
  451. // Don't run action if we don't have desktop
  452. //
  453. CMTRACE1(TEXT("CActionList::Run/GetUserObjectInformation failed, GLE=%u"), GetLastError());
  454. continue;
  455. }
  456. }
  457. else
  458. {
  459. hProcess = pAction->RunAsExe(&pArgs->m_ShellDll);
  460. if (NULL != hProcess)
  461. {
  462. pArgs->Log.Log(CUSTOMACTIONEXE, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram());
  463. }
  464. else
  465. {
  466. pArgs->Log.Log(CUSTOMACTION_WONT_RUN, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram());
  467. }
  468. }
  469. if (hProcess)
  470. {
  471. if (fAddWatch)
  472. {
  473. AddWatchProcess(pArgs,hProcess); // watch for process termination
  474. }
  475. else
  476. {
  477. CloseHandle(hProcess);
  478. }
  479. }
  480. }
  481. }
  482. return TRUE;
  483. }
  484. //+----------------------------------------------------------------------------
  485. //
  486. // Function: CAction::ParseCmdLine
  487. //
  488. // Synopsis: This function parses the given command line into the program,
  489. // dll function name (if required), and the parameters (if any).
  490. // The individual command line parts are stored in member vars.
  491. //
  492. // Arguments: LPTSTR pszCmdLine - connect action command line to parse
  493. //
  494. // Returns: Nothing
  495. //
  496. // History: quintinb original code in Profwiz.cpp ReadConList()
  497. // fengsun copied and modified 4/16/98
  498. // quintinb Rewrote and commonized with the Profwiz version 04/21/00
  499. //
  500. //+----------------------------------------------------------------------------
  501. void CAction::ParseCmdLine(LPTSTR pszCmdLine)
  502. {
  503. m_pszFunction = m_pszProgram = m_pszParams = NULL;
  504. CmStrTrim(pszCmdLine);
  505. HRESULT hr = HrParseCustomActionString(pszCmdLine, &m_pszProgram, &m_pszParams, &m_pszFunction);
  506. MYDBGASSERT(SUCCEEDED(hr));
  507. if (NULL == m_pszProgram)
  508. {
  509. MYDBGASSERT(FALSE); // we should never have a NULL program
  510. m_pszProgram = CmStrCpyAlloc(TEXT(""));
  511. }
  512. if (NULL == m_pszParams)
  513. {
  514. m_pszParams = CmStrCpyAlloc(TEXT(""));
  515. }
  516. if (NULL == m_pszFunction)
  517. {
  518. m_pszFunction = CmStrCpyAlloc(TEXT(""));
  519. }
  520. //
  521. // If we have a function, then the program was a Dll
  522. //
  523. m_fIsDll = (m_pszFunction && (TEXT('\0') != m_pszFunction[0]));
  524. }
  525. //+----------------------------------------------------------------------------
  526. //
  527. // Function: CAction::CAction
  528. //
  529. // Synopsis: Constructor
  530. //
  531. // Arguments: LPTSTR lpCommandLine - The command read from the profile
  532. // CAction is responsible to free it
  533. // UINT dwFlags - The flags read from the profile
  534. // LPTSTR lpDescript - The description of the connect action read from
  535. // profile. CAction is responsible to free it.
  536. //
  537. // Returns: Nothing
  538. //
  539. // History: fengsun Created Header 4/15/98
  540. //
  541. //+----------------------------------------------------------------------------
  542. CAction::CAction(LPTSTR lpCommandLine, UINT dwFlags, LPTSTR lpDescript)
  543. {
  544. m_dwFlags = dwFlags;
  545. m_pszDescription = lpDescript;
  546. //
  547. // Get all information from command line, including
  548. // Program name, function name, parameters
  549. //
  550. ParseCmdLine(lpCommandLine);
  551. //
  552. // If this is a DLL, but there is no description, use the name of the file
  553. // Can not use C Run Time routine _tsplitpath()
  554. //
  555. if (m_fIsDll && (m_pszDescription == NULL || m_pszDescription[0]==TEXT('\0')))
  556. {
  557. //
  558. // Find the last '\\' to get only the file name
  559. //
  560. LPTSTR pszTmp = CmStrrchr(m_pszProgram, '\\');
  561. if (pszTmp == NULL)
  562. {
  563. pszTmp = m_pszProgram;
  564. }
  565. else
  566. {
  567. pszTmp++;
  568. }
  569. CmFree(m_pszDescription);
  570. m_pszDescription = CmStrCpyAlloc(pszTmp);
  571. }
  572. }
  573. CAction::~CAction()
  574. {
  575. CmFree(m_pszProgram);
  576. CmFree(m_pszParams);
  577. CmFree(m_pszFunction);
  578. CmFree(m_pszDescription);
  579. }
  580. //+----------------------------------------------------------------------------
  581. //
  582. // Function: CAction::RunAsDll
  583. //
  584. // Synopsis: Run the action as a Dll
  585. // Format is: DllName.dll FunctionName Argument
  586. // Long file name is enclosed by '+'
  587. //
  588. // Arguments: HWND hwndDlg - The parent window
  589. // DWORD& dwReturnValue - The return value of the dll fuction
  590. // DWORD dwLoadType - The permitted load location
  591. //
  592. // Returns: BOOL - TRUE, if the action is a Dll
  593. //
  594. // History: fengsun Created Header 11/14/97
  595. //
  596. //+----------------------------------------------------------------------------
  597. BOOL CAction::RunAsDll(HWND hwndDlg, OUT DWORD& dwReturnValue, DWORD dwLoadType) const
  598. {
  599. MYDBGASSERT(IsDll());
  600. dwReturnValue = FALSE;
  601. LPWSTR pszwModuleName = NULL;
  602. //
  603. // Determine the module name to be used
  604. //
  605. if (!GetLoadDirWithAlloc(dwLoadType, &pszwModuleName))
  606. {
  607. CMASSERTMSG(FALSE, TEXT("CAction::RunAsDll -- GetLoadDirWithAlloc Failed."));
  608. CmFree(pszwModuleName);
  609. return FALSE;
  610. }
  611. //
  612. // Load the module
  613. //
  614. HINSTANCE hLibrary = LoadLibraryExU(pszwModuleName, NULL, 0);
  615. if (NULL == hLibrary)
  616. {
  617. CMTRACE2(TEXT("RunAsDll() LoadLibrary(%s) failed, GLE=%u."),
  618. MYDBGSTR(pszwModuleName), GetLastError());
  619. CmFree(pszwModuleName);
  620. return FALSE;
  621. }
  622. pfnCmConnectActionFunc pfnFunc;
  623. LPSTR pszFunctionName = NULL;
  624. LPSTR pszParams = NULL;
  625. #ifdef UNICODE
  626. pszFunctionName = WzToSzWithAlloc(m_pszFunction);
  627. #else
  628. pszFunctionName = m_pszFunction;
  629. #endif
  630. //
  631. // Get the Procedure Address
  632. //
  633. pfnFunc = (pfnCmConnectActionFunc)GetProcAddress(hLibrary, pszFunctionName);
  634. #ifdef UNICODE
  635. CmFree(pszFunctionName);
  636. #endif
  637. if (pfnFunc)
  638. {
  639. #if !defined (DEBUG)
  640. __try
  641. {
  642. #endif
  643. #ifdef UNICODE
  644. pszParams = WzToSzWithAlloc(m_pszParams);
  645. #else
  646. pszParams = m_pszParams;
  647. #endif
  648. //
  649. // Execute the Function
  650. //
  651. dwReturnValue = pfnFunc(hwndDlg, hLibrary, pszParams, SW_SHOW);
  652. #ifdef UNICODE
  653. CmFree(pszParams);
  654. #endif
  655. CMTRACE1(TEXT("RunAsDll() Executed module: %s"), MYDBGSTR(pszwModuleName));
  656. CMTRACE1(TEXT("\tFunction: %s"), MYDBGSTR(m_pszFunction));
  657. CMTRACE1(TEXT("\tParams: %s"), MYDBGSTR(m_pszParams));
  658. CMTRACE2(TEXT("\t Return Value: %u = 0x%x"), dwReturnValue, dwReturnValue);
  659. #if !defined (DEBUG)
  660. }
  661. __except(EXCEPTION_EXECUTE_HANDLER)
  662. {
  663. }
  664. #endif
  665. }
  666. else
  667. {
  668. dwReturnValue = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  669. CMTRACE3(TEXT("RunAsDll() GetProcAddress(*pszwModuleName=%s,*m_pszFunction=%s) failed, GLE=%u."),
  670. MYDBGSTR(pszwModuleName), MYDBGSTR(m_pszFunction), GetLastError());
  671. }
  672. CmFree(pszwModuleName);
  673. FreeLibrary(hLibrary);
  674. return TRUE;
  675. }
  676. //+----------------------------------------------------------------------------
  677. //
  678. // Function: CAction::RunAsExe
  679. //
  680. // Synopsis: Run the action as an exe or other shell object
  681. //
  682. // Arguments: CShellDll* pShellDll, pointer to the link to shell32.dll
  683. //
  684. // Returns: HANDLE - The action Process handle, for Win32 only
  685. //
  686. // History: fengsun Created Header 11/14/97
  687. //
  688. //+----------------------------------------------------------------------------
  689. HANDLE CAction::RunAsExe(CShellDll* pShellDll) const
  690. {
  691. // Now we have the exe name and args separated, execute it
  692. SHELLEXECUTEINFO seiInfo;
  693. ZeroMemory(&seiInfo,sizeof(seiInfo));
  694. seiInfo.cbSize = sizeof(seiInfo);
  695. seiInfo.fMask |= SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;
  696. seiInfo.lpFile = m_pszProgram;
  697. seiInfo.lpParameters = m_pszParams;
  698. seiInfo.nShow = SW_SHOW;
  699. MYDBGASSERT(pShellDll);
  700. if (!pShellDll->ExecuteEx(&seiInfo))
  701. {
  702. CMTRACE3(TEXT("RunAsExe() ShellExecuteEx() of %s %s GLE=%u."),
  703. MYDBGSTR(m_pszProgram), MYDBGSTR(m_pszParams), GetLastError());
  704. return NULL;
  705. }
  706. return seiInfo.hProcess;
  707. }
  708. //+----------------------------------------------------------------------------
  709. //
  710. // Function: CAction::GetLoadDirWithAlloc
  711. //
  712. // Synopsis: Uses the dwLoadType parameter to decide how the path should be
  713. // modified. This is used in the WinLogon context to prevent just
  714. // any executable from being executed. Must be from the profile dir
  715. // or the system dir.
  716. //
  717. // Arguments: DWORD dwLoadType - Load type, currently 0 == system dir, 1 == profile dir (default)
  718. // LPWSTR pszwPath - string buffer to put the modified path in
  719. //
  720. // Returns: BOOL - TRUE if successful
  721. //
  722. // History: quintinb Created 01/11/2000
  723. // sumitc Change to alloc retval 05/08/2000
  724. //
  725. //+----------------------------------------------------------------------------
  726. BOOL CAction::GetLoadDirWithAlloc(IN DWORD dwLoadType, OUT LPWSTR * ppszwPath) const
  727. {
  728. LPWSTR psz = NULL;
  729. UINT cch = 0;
  730. //
  731. // Check that we have an output buffer
  732. //
  733. if (NULL == ppszwPath)
  734. {
  735. return FALSE;
  736. }
  737. //
  738. // Compute how much space we need
  739. //
  740. if (dwLoadType)
  741. {
  742. // 1 = profile dir
  743. cch += lstrlen(m_pszProgram) + 1;
  744. }
  745. else
  746. {
  747. // 0 = system dir
  748. cch = GetSystemDirectoryU(NULL, 0);
  749. cch += lstrlen(TEXT("\\"));
  750. cch += lstrlen(m_pszProgram) + 1; // is the +1 already in the GetSystemDir retval?
  751. }
  752. //
  753. // Allocate it
  754. //
  755. psz = (LPWSTR) CmMalloc(sizeof(TCHAR) * cch);
  756. if (NULL == psz)
  757. {
  758. return FALSE;
  759. }
  760. //
  761. // Process the load type
  762. //
  763. if (dwLoadType)
  764. {
  765. //
  766. // If relative path, this will already be expanded.
  767. //
  768. lstrcpyU(psz, m_pszProgram);
  769. }
  770. else
  771. {
  772. //
  773. // Force the system directory
  774. //
  775. if (0 == GetSystemDirectoryU(psz, cch))
  776. {
  777. CmFree(psz);
  778. return FALSE;
  779. }
  780. lstrcatU(psz, TEXT("\\"));
  781. lstrcatU(psz, m_pszProgram);
  782. }
  783. *ppszwPath = psz;
  784. return TRUE;
  785. }
  786. //+----------------------------------------------------------------------------
  787. //
  788. // Function: CAction::RunAsExeFromSystem
  789. //
  790. // Synopsis: Run the action as an exe or other shell object on the choosen desktop
  791. //
  792. // Arguments: CShellDll* pShellDll - pointer to the link to shell32.dll
  793. // LPTSTR pszDesktop - name of the desktop to execute the exe on
  794. // DWORD dwLoadType - location from which to load the exe
  795. //
  796. // Returns: HANDLE - The action Process handle, for Win32 only
  797. //
  798. // History: v-vijayb Created 07/19/99
  799. // nickball Removed fSecurity 07/27/99
  800. //
  801. //+----------------------------------------------------------------------------
  802. HANDLE CAction::RunAsExeFromSystem(CShellDll* pShellDll, LPTSTR pszDesktop, DWORD dwLoadType)
  803. {
  804. STARTUPINFO StartupInfo = {0};
  805. PROCESS_INFORMATION ProcessInfo = {0};
  806. LPWSTR pszwFullPath = NULL;
  807. LPWSTR pszwCommandLine = NULL;
  808. MYDBGASSERT(OS_NT);
  809. StartupInfo.cb = sizeof(StartupInfo);
  810. if (pszDesktop)
  811. {
  812. StartupInfo.lpDesktop = pszDesktop;
  813. StartupInfo.wShowWindow = SW_SHOW;
  814. }
  815. //
  816. // Use an explicit path to the modules to be launched, this
  817. // prevents CreateProcess from picking something up on the path.
  818. //
  819. if (!GetLoadDirWithAlloc(dwLoadType, &pszwFullPath))
  820. {
  821. CMASSERTMSG(FALSE, TEXT("CAction::RunAsExeFromSystem -- GetLoadDirWithAlloc Failed."));
  822. goto Cleanup;
  823. }
  824. pszwCommandLine = CmStrCpyAlloc(m_pszProgram);
  825. if (NULL == pszwCommandLine)
  826. {
  827. CMASSERTMSG(FALSE, TEXT("CAction::RunAsExeFromSystem -- CmStrCpyAlloc Failed."));
  828. goto Cleanup;
  829. }
  830. //
  831. // Add parameters
  832. //
  833. if (NULL == CmStrCatAlloc(&pszwCommandLine, TEXT(" ")))
  834. {
  835. goto Cleanup;
  836. }
  837. if (NULL == CmStrCatAlloc(&pszwCommandLine, m_pszParams))
  838. {
  839. goto Cleanup;
  840. }
  841. CMTRACE1(TEXT("RunAsExeFromSystem/CreateProcess() - Launching %s"), pszwCommandLine);
  842. //
  843. // Launch the modules, this could be CreateProcessU but it isn't necessary as this only runs on NT
  844. //
  845. if (NULL == CreateProcess(pszwFullPath, pszwCommandLine,
  846. NULL, NULL, FALSE, 0,
  847. NULL, NULL,
  848. &StartupInfo, &ProcessInfo))
  849. {
  850. CMTRACE2(TEXT("RunAsExeFromSystem() CreateProcess() of %s failed, GLE=%u."), pszwCommandLine, GetLastError());
  851. ProcessInfo.hProcess = NULL;
  852. ProcessInfo.hThread = NULL;
  853. }
  854. Cleanup:
  855. if (ProcessInfo.hThread)
  856. {
  857. CloseHandle(ProcessInfo.hThread);
  858. }
  859. CmFree(pszwFullPath);
  860. CmFree(pszwCommandLine);
  861. return ProcessInfo.hProcess;
  862. }
  863. //+----------------------------------------------------------------------------
  864. //
  865. // Function: CAction::ExpandMacros
  866. //
  867. // Synopsis: Replace the %xxxxx% in command line with the corresponding value
  868. //
  869. // Arguments: ArgsStruct *pArgs -
  870. //
  871. // Returns: Nothing
  872. //
  873. // History: fengsun Created Header 11/14/97
  874. //
  875. //+----------------------------------------------------------------------------
  876. void CAction::ExpandMacros(ArgsStruct *pArgs)
  877. {
  878. MYDBGASSERT(pArgs);
  879. LPTSTR pszCurr = m_pszParams;
  880. BOOL bValidPropertyName;
  881. while (*pszCurr)
  882. {
  883. if (*pszCurr == TEXT('%'))
  884. {
  885. LPTSTR pszNextPercent = CmStrchr(pszCurr + 1, TEXT('%'));
  886. if (pszNextPercent)
  887. {
  888. LPTSTR pszTmp = (LPTSTR) CmMalloc((DWORD)((pszNextPercent-pszCurr))*sizeof(TCHAR));
  889. if (pszTmp)
  890. {
  891. CopyMemory(pszTmp,pszCurr+1,(pszNextPercent-pszCurr-1)*sizeof(TCHAR));
  892. //
  893. // Get the value from name
  894. //
  895. LPTSTR pszMid = pArgs->GetProperty(pszTmp, &bValidPropertyName);
  896. //
  897. // If the property does not exist, use "NULL"
  898. //
  899. if (pszMid == NULL)
  900. {
  901. pszMid = CmStrCpyAlloc(TEXT("NULL"));
  902. }
  903. else if (pszMid[0] == TEXT('\0'))
  904. {
  905. CmFree(pszMid);
  906. pszMid = CmStrCpyAlloc(TEXT("NULL"));
  907. }
  908. else if ( (lstrcmpiU(pszTmp,TEXT("Profile")) == 0) ||
  909. CmStrchr(pszMid, TEXT(' ')) != NULL)
  910. {
  911. //
  912. // If the name is %Profile% or the value has a space in it,
  913. // Put the string in double quote
  914. //
  915. LPTSTR pszValueInQuote = (LPTSTR)CmMalloc((lstrlenU(pszMid)+3)*sizeof(pszMid[0]));
  916. if (pszValueInQuote)
  917. {
  918. lstrcpyU(pszValueInQuote, TEXT("\""));
  919. lstrcatU(pszValueInQuote, pszMid);
  920. lstrcatU(pszValueInQuote, TEXT("\""));
  921. CmFree(pszMid);
  922. pszMid = pszValueInQuote;
  923. }
  924. else
  925. {
  926. CMTRACE1(TEXT("ExpandMacros() malloc failed, can't put string in double quotes, GLE=%u."), GetLastError());
  927. }
  928. }
  929. //
  930. // if bValidPropertyName is FALSE then leave untouched.
  931. //
  932. if (FALSE == bValidPropertyName)
  933. {
  934. pszCurr = pszNextPercent + 1;
  935. }
  936. else
  937. {
  938. //
  939. // Replace %xxxx% with the value
  940. //
  941. DWORD dwLenPre = (DWORD)(pszCurr - m_pszParams);
  942. DWORD dwLenMid = lstrlenU(pszMid);
  943. DWORD dwLenPost = lstrlenU(pszNextPercent+1);
  944. CmFree(pszTmp);
  945. pszTmp = m_pszParams;
  946. m_pszParams = (LPTSTR) CmMalloc((dwLenPre + dwLenMid + dwLenPost + 1)*sizeof(TCHAR));
  947. if (m_pszParams)
  948. {
  949. CopyMemory(m_pszParams, pszTmp, dwLenPre*sizeof(TCHAR)); // before %
  950. lstrcatU(m_pszParams, pszMid); //append value
  951. lstrcatU(m_pszParams, pszNextPercent+1); // after %
  952. pszCurr = m_pszParams + dwLenPre + dwLenMid;
  953. }
  954. else
  955. {
  956. // we're out of memory
  957. CMTRACE1(TEXT("ExpandMacros() malloc failed, can't strip off %% signs, GLE=%u."), GetLastError());
  958. m_pszParams = pszTmp;
  959. }
  960. }
  961. CmFree(pszMid);
  962. }
  963. CmFree(pszTmp);
  964. }
  965. else
  966. {
  967. pszCurr++;
  968. }
  969. }
  970. else
  971. {
  972. pszCurr++;
  973. }
  974. }
  975. }
  976. #ifdef DEBUG
  977. //+----------------------------------------------------------------------------
  978. //
  979. // Function: CAction::AssertValid
  980. //
  981. // Synopsis: For debug purpose only, assert the connection object is valid
  982. //
  983. // Arguments: None
  984. //
  985. // Returns: Nothing
  986. //
  987. // History: Created Header 2/12/98
  988. //
  989. //+----------------------------------------------------------------------------
  990. void CAction::AssertValid() const
  991. {
  992. MYDBGASSERT(m_pszProgram && m_pszProgram[0]);
  993. MYDBGASSERT(m_fIsDll == TRUE || m_fIsDll == FALSE);
  994. }
  995. #endif
  996. //+----------------------------------------------------------------------------
  997. //
  998. // Function: CAction::ExpandEnvironmentStrings
  999. //
  1000. // Synopsis: Utility fn to expand environment variables in the given string
  1001. //
  1002. // Arguments: ppsz - ptr to string (usually member variable)
  1003. //
  1004. // Returns: Nothing
  1005. //
  1006. // History: SumitC Created 29-Feb-2000
  1007. //
  1008. //+----------------------------------------------------------------------------
  1009. void CAction::ExpandEnvironmentStrings(LPTSTR * ppsz)
  1010. {
  1011. DWORD cLen;
  1012. MYDBGASSERT(*ppsz);
  1013. //
  1014. // find out how much memory we need to allocate
  1015. //
  1016. cLen = ExpandEnvironmentStringsU(*ppsz, NULL, 0);
  1017. if (cLen)
  1018. {
  1019. LPTSTR pszTemp = (LPTSTR) CmMalloc((cLen + 1) * sizeof(TCHAR));
  1020. if (pszTemp)
  1021. {
  1022. DWORD cLen2 = ExpandEnvironmentStringsU(*ppsz, pszTemp, cLen);
  1023. MYDBGASSERT(cLen == cLen2);
  1024. if (cLen2)
  1025. {
  1026. CmFree(*ppsz);
  1027. *ppsz = pszTemp;
  1028. }
  1029. }
  1030. }
  1031. }
  1032. //+----------------------------------------------------------------------------
  1033. //
  1034. // Function: CAction::IsAllowed
  1035. //
  1036. // Synopsis: checks Registry to see if a command is allowed to run
  1037. //
  1038. // Arguments: _ArgsStruct *pArgs - Ptr to global args struct
  1039. // LPDWORD lpdwLoadType - Ptr to DWORD to be filled with load type
  1040. //
  1041. // Returns: TRUE if action is allowed @ this time
  1042. //
  1043. // Notes: Checks SOFTWARE\Microsoft\Connection Manager\<ServiceName>
  1044. // Under which you will have the Values for each command
  1045. // 0 - system32 directory
  1046. // 1 - profile directory
  1047. // History: v-vijayb Created Header 7/20/99
  1048. //
  1049. //+----------------------------------------------------------------------------
  1050. BOOL CAction::IsAllowed(_ArgsStruct *pArgs, LPDWORD lpdwLoadType)
  1051. {
  1052. return IsActionEnabled(m_pszProgram, pArgs->szServiceName, pArgs->piniService->GetFile(), lpdwLoadType);
  1053. }
  1054. //+----------------------------------------------------------------------------
  1055. //
  1056. // Function: CAction::RunConnectActionForCurrentConnection
  1057. //
  1058. // Synopsis: This function compares the flags value of the connect action
  1059. // with the current connection type (from pArgs->GetTypeOfConnection).
  1060. // It returns TRUE if the connect action should be run for this type
  1061. // and FALSE if the connect action should be skipped.
  1062. //
  1063. // Arguments: _ArgsStruct *pArgs - Ptr to global args struct
  1064. //
  1065. // Returns: TRUE if action should be executed
  1066. //
  1067. // History: quintinb Created 04/20/00
  1068. //
  1069. //+----------------------------------------------------------------------------
  1070. BOOL CAction::RunConnectActionForCurrentConnection(_ArgsStruct *pArgs)
  1071. {
  1072. BOOL bReturn = TRUE;
  1073. DWORD dwType = pArgs->GetTypeOfConnection();
  1074. if (DIAL_UP_CONNECTION == dwType)
  1075. {
  1076. //
  1077. // Don't run direct only or tunnel connect actions
  1078. // on a dialup connection.
  1079. //
  1080. if ((m_dwFlags & DIRECT_ONLY) || (m_dwFlags & ALL_TUNNEL))
  1081. {
  1082. bReturn = FALSE;
  1083. }
  1084. }
  1085. else if (DIRECT_CONNECTION == dwType)
  1086. {
  1087. //
  1088. // Don't run dialup only or dialup connect actions
  1089. // on a direct connection.
  1090. //
  1091. if ((m_dwFlags & DIALUP_ONLY) || (m_dwFlags & ALL_DIALUP))
  1092. {
  1093. bReturn = FALSE;
  1094. }
  1095. }
  1096. else if (DOUBLE_DIAL_CONNECTION == dwType)
  1097. {
  1098. //
  1099. // Don't run dialup only or dialup connect actions
  1100. // on a direct connection.
  1101. //
  1102. if ((m_dwFlags & DIALUP_ONLY) || (m_dwFlags & DIRECT_ONLY))
  1103. {
  1104. bReturn = FALSE;
  1105. }
  1106. }
  1107. else
  1108. {
  1109. CMASSERTMSG(FALSE, TEXT("CActionList::Run -- unknown connection type, skipping action"));
  1110. bReturn = FALSE;
  1111. }
  1112. return bReturn;
  1113. }