//+---------------------------------------------------------------------------- // // File: ActList.cpp // // Module: CMDIAL32.DLL // // Synopsis: Implement the two connect action list class // CAction and CActionList // // Copyright (c) 1997-1999 Microsoft Corporation // // Author: fengsun Created 11/14/97 // //+---------------------------------------------------------------------------- #include "cmmaster.h" #include "ActList.h" #include "stp_str.h" // // Include the custom action parsing routine that CM and CMAK now share, HrParseCustomActionString // #include "parseca.cpp" // // Constructor and destructor // CActionList::CActionList() { m_pActionList = NULL; m_nNum = 0; m_nSize = 0; m_pszType = NULL; } CActionList::~CActionList() { for (UINT i = 0; i < m_nNum; i++) { delete m_pActionList[i]; } CmFree(m_pActionList); } //+---------------------------------------------------------------------------- // // Function: CActionList::Add // // Synopsis: Dynamic array function. Append the element at the end of the array // Grow the array if nessesary // // Arguments: CAction* pAction - element to be added // // Returns: Nothing // // History: Fengsun Created Header 11/14/97 // tomkel Fixed PREFIX issues 11/21/2000 // //+---------------------------------------------------------------------------- void CActionList::Add(CAction* pAction) { MYDBGASSERT(m_nNum <= m_nSize); MYDBGASSERT(m_nSize == 0 || m_pActionList!=NULL); // if (m_nSize!=0) ASSERT(m_pActionList!=NULL); m_nNum++; if (m_nNum > m_nSize) { // // Either there is not enough room OR m_pActionList is NULL (this // is the first call to Add). Need to allocate memory // CAction** pNewList = (CAction**)CmMalloc((m_nSize + GROW_BY)*sizeof(CAction*)); MYDBGASSERT(pNewList); if (m_pActionList && pNewList) { // // Memory was allocated and there is something to copy from m_pActionList // CopyMemory(pNewList, m_pActionList, (m_nSize)*sizeof(CAction*)); } if (pNewList) { // // Memory was allocated // CmFree(m_pActionList); m_pActionList = pNewList; m_nSize += GROW_BY; // // Add the action // m_pActionList[m_nNum - 1] = pAction; } else { // // Memory was not allocated, so Add did not happen // Need to decrement the number of items in list (m_nNum) // since it was inceremented at the beginning. // m_nNum--; } } else { // // Just add the action to the end // m_pActionList[m_nNum - 1] = pAction; } } //+---------------------------------------------------------------------------- // // Function: CActionList::GetAt // // Synopsis: Dynamic array fuction. Get the element at nIndex // // Arguments: UINT nIndex - // // Returns: inline CAction* - // // History: fengsun Created Header 11/14/97 // //+---------------------------------------------------------------------------- inline CAction* CActionList::GetAt(UINT nIndex) { MYDBGASSERT(nIndexGPPS(pszSection, szEntry); // Command line if (*pszCmd == TEXT('\0')) { // // No more entries // CmFree(pszCmd); break; } // // Read the flag // UINT iFlag = 0; if (pszSection && pszSection[0]) { wsprintfU(szEntry, c_pszCmEntryConactFlags, dwIdx); //0&Flags iFlag = (UINT)piniService->GPPI(pszSection, szEntry, 0); } // // Read the description // LPTSTR pszDescript = NULL; wsprintfU(szEntry, c_pszCmEntryConactDesc, dwIdx); //0&Description pszDescript = piniService->GPPS(pszSection, szEntry); // // CAction is responsible for releasing pszDescript // CAction* pAction = new CAction(pszCmd, iFlag, pszDescript); CmFree(pszCmd); if (pAction) { pAction->ConvertRelativePath(piniService); ASSERT_VALID(pAction); pAction->ExpandEnvironmentStringsInCommand(); Add(pAction); bRet = TRUE; } } if (bRet) { m_pszType = pszSection; } return bRet; } //+---------------------------------------------------------------------------- // // Function: CActionList::RunAccordType // // Synopsis: Run the action list according to the connection type // // Arguments: HWND hwndDlg - The parent window // _ArgsStruct *pArgs - // BOOL fStatusMsgOnFailure - Whether to display a status message // to the user in the event of failure // BOOL fOnError - are we running OnError connect action? // // Returns: BOOL - FALSE, if some sync action failed to start or returns failed // // History: Fengsun Created Header 12/5/97 // //+---------------------------------------------------------------------------- BOOL CActionList::RunAccordType(HWND hwndDlg, _ArgsStruct *pArgs, BOOL fStatusMsgOnFailure, BOOL fOnError) { // // Set the flag, so CM will not handle WM_TIMER and RAS messages // pArgs->fIgnoreTimerRasMsg = TRUE; BOOL fRetValue = Run(hwndDlg, pArgs, FALSE, fStatusMsgOnFailure, fOnError);//fAddWatch = FALSE pArgs->fIgnoreTimerRasMsg = FALSE; return fRetValue; } //+---------------------------------------------------------------------------- // // Function: CActionList::Run // // Synopsis: Run the action list // // Arguments: HWND hwndDlg - The parent window, which is diabled during the process // ArgsStruct *pArgs - // BOOL fAddWatch - If true, will add the process as watch process, // BOOL fStatusMsgOnFailure - Whether to display a status message // to the user in the event of failure // BOOL fOnError - are we running OnError connect action? // // Returns: BOOL - FALSE, if some sync action failed to start or returns failed // // History: fengsun Created Header 11/14/97 // //+---------------------------------------------------------------------------- BOOL CActionList::Run(HWND hwndDlg, ArgsStruct *pArgs, BOOL fAddWatch, BOOL fStatusMsgOnFailure, BOOL fOnError) { // // Disable the window, and enable it on return // CFreezeWindow FreezeWindow(hwndDlg); for (UINT i = 0; i < GetSize(); i++) { CAction* pAction = (CAction*)GetAt(i); DWORD dwLoadType = (DWORD)-1; ASSERT_VALID(pAction); MYDBGASSERT(m_pszType); // // Lets check the flags value to see if this connect action should // run for this type of connection. // if (FALSE == pAction->RunConnectActionForCurrentConnection(pArgs)) { continue; } // // Replace %xxxx% with the value // pAction->ExpandMacros(pArgs); // // Also expand any environment variables // NOTE: the order (macros vs. env vars) is deliberate. Macros get // expanded first. // pAction->ExpandEnvironmentStringsInParams(); // // Check to see if we can run the action @ this moment // if (FALSE == pAction->IsAllowed(pArgs, &dwLoadType)) { // // If not allowed, log the fact that we didn't run this connect action // and then just skip it. // pArgs->Log.Log(CUSTOMACTION_NOT_ALLOWED, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram()); continue; } // // If this customaction might bring up UI // if (pAction->HasUI()) { // // If we are in unattended mode, don't run any connect actions // if (pArgs->dwFlags & FL_UNATTENDED) { pArgs->Log.Log(CUSTOMACTION_NOT_ALLOWED, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram()); CMTRACE(TEXT("Run: skipped past a customaction because we are in unattended mode")); continue; } // // Custom actions processed during a Fast User Switch can put up UI requiring // user input, effectively blocking CM. // if (pArgs->fInFastUserSwitch) { CMASSERTMSG((CM_CREDS_GLOBAL != pArgs->dwCurrentCredentialType), TEXT("CActionList::Run - in FUS disconnect, but connectoid has global creds!")); pArgs->Log.Log(CUSTOMACTION_NOT_ALLOWED, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram()); CMTRACE(TEXT("Run: skipped past a singleuser DLL connectaction because of FUS")); continue; } } if (pAction->IsDll()) { DWORD dwActionRetValue=0; // the connect action return value, in COM format BOOL bLoadSucceed = FALSE; if (hwndDlg) { // // Display description for DLL // if (pAction->GetDescription()) { LPTSTR lpszText = CmFmtMsg(g_hInst, IDMSG_CONN_ACTION_RUNNING, pAction->GetDescription()); // // Update the main dialog status window // SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, lpszText); CmFree(lpszText); } } bLoadSucceed = pAction->RunAsDll(hwndDlg, dwActionRetValue, dwLoadType); if (bLoadSucceed) { pArgs->Log.Log(CUSTOMACTIONDLL, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram(), dwActionRetValue); } else { pArgs->Log.Log(CUSTOMACTION_WONT_RUN, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram()); } // // Failed to start the action, or the action returned failure // if (FAILED(dwActionRetValue) || !bLoadSucceed) { LPTSTR lpszText = NULL; if (fStatusMsgOnFailure && hwndDlg && pAction->GetDescription()) { if (bLoadSucceed) { lpszText = CmFmtMsg(g_hInst, IDMSG_CONN_ACTION_FAILED, pAction->GetDescription(), dwActionRetValue); } else { lpszText = CmFmtMsg(g_hInst, IDMSG_CONN_ACTION_NOTFOUND, pAction->GetDescription()); } // // Update the main dialog status window // SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, lpszText); } if (!fOnError) { DWORD dwError = 0; if (bLoadSucceed) { dwError = dwActionRetValue; } else { dwError = ERROR_DLL_NOT_FOUND; } pArgs->Log.Log(ONERROR_EVENT, dwError, pAction->GetDescription()); // // We'll run On-Error connect actions if we are not already running OnError // connect action. This is to prevent infinite loops. // CActionList OnErrorActList; OnErrorActList.Append(pArgs->piniService, c_pszCmSectionOnError); // // fStatusMsgOnFailure = FALSE // OnErrorActList.RunAccordType(hwndDlg, pArgs, FALSE, TRUE); // // Update the program state // if (fStatusMsgOnFailure) { lstrcpynU(pArgs->szLastErrorSrc, pAction->GetDescription(), MAX_LASTERR_LEN); pArgs->dwExitCode = dwError; SetInteractive(pArgs->hwndMainDlg, pArgs); pArgs->psState = PS_Error; } } if (lpszText) { // // restore the failure msg of the previous connect action // SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, lpszText); CmFree(lpszText); } // // Note that if a DLL connect action fails, we will stop processing connect actions. // If the fStatusMsgOnFailure flag is set, then we won't show an error message // but connect action processing will still halt (we do this in cases where the user // isn't going to care such as oncancel actions, onerror actions, and cases where // disconnect action fail). // return FALSE; } } else { HANDLE hProcess = NULL; TCHAR szDesktopName[MAX_PATH]; TCHAR szWinDesktop[MAX_PATH]; if (IsLogonAsSystem()) { DWORD cb; HDESK hDesk = GetThreadDesktop(GetCurrentThreadId()); // // Get the name of the desktop. Normally returns default or Winlogon or system or WinNT // On Win95/98 GetUserObjectInformation is not supported and thus the desktop name // will be empty so we will use the good old API // szDesktopName[0] = 0; if (hDesk && GetUserObjectInformation(hDesk, UOI_NAME, szDesktopName, sizeof(szDesktopName), &cb)) { lstrcpyU(szWinDesktop, TEXT("Winsta0\\")); lstrcatU(szWinDesktop, szDesktopName); CMTRACE1(TEXT("CActionList::Run - Desktop = %s"), MYDBGSTR(szWinDesktop)); hProcess = pAction->RunAsExeFromSystem(&pArgs->m_ShellDll, szWinDesktop, dwLoadType); if (NULL != hProcess) { pArgs->Log.Log(CUSTOMACTIONEXE, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram()); } else { pArgs->Log.Log(CUSTOMACTION_WONT_RUN, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram()); } } else { // // Don't run action if we don't have desktop // CMTRACE1(TEXT("CActionList::Run/GetUserObjectInformation failed, GLE=%u"), GetLastError()); continue; } } else { hProcess = pAction->RunAsExe(&pArgs->m_ShellDll); if (NULL != hProcess) { pArgs->Log.Log(CUSTOMACTIONEXE, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram()); } else { pArgs->Log.Log(CUSTOMACTION_WONT_RUN, m_pszType, SAFE_LOG_ARG(pAction->GetDescription()), pAction->GetProgram()); } } if (hProcess) { if (fAddWatch) { AddWatchProcess(pArgs,hProcess); // watch for process termination } else { CloseHandle(hProcess); } } } } return TRUE; } //+---------------------------------------------------------------------------- // // Function: CAction::ParseCmdLine // // Synopsis: This function parses the given command line into the program, // dll function name (if required), and the parameters (if any). // The individual command line parts are stored in member vars. // // Arguments: LPTSTR pszCmdLine - connect action command line to parse // // Returns: Nothing // // History: quintinb original code in Profwiz.cpp ReadConList() // fengsun copied and modified 4/16/98 // quintinb Rewrote and commonized with the Profwiz version 04/21/00 // //+---------------------------------------------------------------------------- void CAction::ParseCmdLine(LPTSTR pszCmdLine) { m_pszFunction = m_pszProgram = m_pszParams = NULL; CmStrTrim(pszCmdLine); HRESULT hr = HrParseCustomActionString(pszCmdLine, &m_pszProgram, &m_pszParams, &m_pszFunction); MYDBGASSERT(SUCCEEDED(hr)); if (NULL == m_pszProgram) { MYDBGASSERT(FALSE); // we should never have a NULL program m_pszProgram = CmStrCpyAlloc(TEXT("")); } if (NULL == m_pszParams) { m_pszParams = CmStrCpyAlloc(TEXT("")); } if (NULL == m_pszFunction) { m_pszFunction = CmStrCpyAlloc(TEXT("")); } // // If we have a function, then the program was a Dll // m_fIsDll = (m_pszFunction && (TEXT('\0') != m_pszFunction[0])); } //+---------------------------------------------------------------------------- // // Function: CAction::CAction // // Synopsis: Constructor // // Arguments: LPTSTR lpCommandLine - The command read from the profile // CAction is responsible to free it // UINT dwFlags - The flags read from the profile // LPTSTR lpDescript - The description of the connect action read from // profile. CAction is responsible to free it. // // Returns: Nothing // // History: fengsun Created Header 4/15/98 // //+---------------------------------------------------------------------------- CAction::CAction(LPTSTR lpCommandLine, UINT dwFlags, LPTSTR lpDescript) { m_dwFlags = dwFlags; m_pszDescription = lpDescript; // // Get all information from command line, including // Program name, function name, parameters // ParseCmdLine(lpCommandLine); // // If this is a DLL, but there is no description, use the name of the file // Can not use C Run Time routine _tsplitpath() // if (m_fIsDll && (m_pszDescription == NULL || m_pszDescription[0]==TEXT('\0'))) { // // Find the last '\\' to get only the file name // LPTSTR pszTmp = CmStrrchr(m_pszProgram, '\\'); if (pszTmp == NULL) { pszTmp = m_pszProgram; } else { pszTmp++; } CmFree(m_pszDescription); m_pszDescription = CmStrCpyAlloc(pszTmp); } } CAction::~CAction() { CmFree(m_pszProgram); CmFree(m_pszParams); CmFree(m_pszFunction); CmFree(m_pszDescription); } //+---------------------------------------------------------------------------- // // Function: CAction::RunAsDll // // Synopsis: Run the action as a Dll // Format is: DllName.dll FunctionName Argument // Long file name is enclosed by '+' // // Arguments: HWND hwndDlg - The parent window // DWORD& dwReturnValue - The return value of the dll fuction // DWORD dwLoadType - The permitted load location // // Returns: BOOL - TRUE, if the action is a Dll // // History: fengsun Created Header 11/14/97 // //+---------------------------------------------------------------------------- BOOL CAction::RunAsDll(HWND hwndDlg, OUT DWORD& dwReturnValue, DWORD dwLoadType) const { MYDBGASSERT(IsDll()); dwReturnValue = FALSE; LPWSTR pszwModuleName = NULL; // // Determine the module name to be used // if (!GetLoadDirWithAlloc(dwLoadType, &pszwModuleName)) { CMASSERTMSG(FALSE, TEXT("CAction::RunAsDll -- GetLoadDirWithAlloc Failed.")); CmFree(pszwModuleName); return FALSE; } // // Load the module // HINSTANCE hLibrary = LoadLibraryExU(pszwModuleName, NULL, 0); if (NULL == hLibrary) { CMTRACE2(TEXT("RunAsDll() LoadLibrary(%s) failed, GLE=%u."), MYDBGSTR(pszwModuleName), GetLastError()); CmFree(pszwModuleName); return FALSE; } pfnCmConnectActionFunc pfnFunc; LPSTR pszFunctionName = NULL; LPSTR pszParams = NULL; #ifdef UNICODE pszFunctionName = WzToSzWithAlloc(m_pszFunction); #else pszFunctionName = m_pszFunction; #endif // // Get the Procedure Address // pfnFunc = (pfnCmConnectActionFunc)GetProcAddress(hLibrary, pszFunctionName); #ifdef UNICODE CmFree(pszFunctionName); #endif if (pfnFunc) { #if !defined (DEBUG) __try { #endif #ifdef UNICODE pszParams = WzToSzWithAlloc(m_pszParams); #else pszParams = m_pszParams; #endif // // Execute the Function // dwReturnValue = pfnFunc(hwndDlg, hLibrary, pszParams, SW_SHOW); #ifdef UNICODE CmFree(pszParams); #endif CMTRACE1(TEXT("RunAsDll() Executed module: %s"), MYDBGSTR(pszwModuleName)); CMTRACE1(TEXT("\tFunction: %s"), MYDBGSTR(m_pszFunction)); CMTRACE1(TEXT("\tParams: %s"), MYDBGSTR(m_pszParams)); CMTRACE2(TEXT("\t Return Value: %u = 0x%x"), dwReturnValue, dwReturnValue); #if !defined (DEBUG) } __except(EXCEPTION_EXECUTE_HANDLER) { } #endif } else { dwReturnValue = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION); CMTRACE3(TEXT("RunAsDll() GetProcAddress(*pszwModuleName=%s,*m_pszFunction=%s) failed, GLE=%u."), MYDBGSTR(pszwModuleName), MYDBGSTR(m_pszFunction), GetLastError()); } CmFree(pszwModuleName); FreeLibrary(hLibrary); return TRUE; } //+---------------------------------------------------------------------------- // // Function: CAction::RunAsExe // // Synopsis: Run the action as an exe or other shell object // // Arguments: CShellDll* pShellDll, pointer to the link to shell32.dll // // Returns: HANDLE - The action Process handle, for Win32 only // // History: fengsun Created Header 11/14/97 // //+---------------------------------------------------------------------------- HANDLE CAction::RunAsExe(CShellDll* pShellDll) const { // Now we have the exe name and args separated, execute it SHELLEXECUTEINFO seiInfo; ZeroMemory(&seiInfo,sizeof(seiInfo)); seiInfo.cbSize = sizeof(seiInfo); seiInfo.fMask |= SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; seiInfo.lpFile = m_pszProgram; seiInfo.lpParameters = m_pszParams; seiInfo.nShow = SW_SHOW; MYDBGASSERT(pShellDll); if (!pShellDll->ExecuteEx(&seiInfo)) { CMTRACE3(TEXT("RunAsExe() ShellExecuteEx() of %s %s GLE=%u."), MYDBGSTR(m_pszProgram), MYDBGSTR(m_pszParams), GetLastError()); return NULL; } return seiInfo.hProcess; } //+---------------------------------------------------------------------------- // // Function: CAction::GetLoadDirWithAlloc // // Synopsis: Uses the dwLoadType parameter to decide how the path should be // modified. This is used in the WinLogon context to prevent just // any executable from being executed. Must be from the profile dir // or the system dir. // // Arguments: DWORD dwLoadType - Load type, currently 0 == system dir, 1 == profile dir (default) // LPWSTR pszwPath - string buffer to put the modified path in // // Returns: BOOL - TRUE if successful // // History: quintinb Created 01/11/2000 // sumitc Change to alloc retval 05/08/2000 // //+---------------------------------------------------------------------------- BOOL CAction::GetLoadDirWithAlloc(IN DWORD dwLoadType, OUT LPWSTR * ppszwPath) const { LPWSTR psz = NULL; UINT cch = 0; // // Check that we have an output buffer // if (NULL == ppszwPath) { return FALSE; } // // Compute how much space we need // if (dwLoadType) { // 1 = profile dir cch += lstrlen(m_pszProgram) + 1; } else { // 0 = system dir cch = GetSystemDirectoryU(NULL, 0); cch += lstrlen(TEXT("\\")); cch += lstrlen(m_pszProgram) + 1; // is the +1 already in the GetSystemDir retval? } // // Allocate it // psz = (LPWSTR) CmMalloc(sizeof(TCHAR) * cch); if (NULL == psz) { return FALSE; } // // Process the load type // if (dwLoadType) { // // If relative path, this will already be expanded. // lstrcpyU(psz, m_pszProgram); } else { // // Force the system directory // if (0 == GetSystemDirectoryU(psz, cch)) { CmFree(psz); return FALSE; } lstrcatU(psz, TEXT("\\")); lstrcatU(psz, m_pszProgram); } *ppszwPath = psz; return TRUE; } //+---------------------------------------------------------------------------- // // Function: CAction::RunAsExeFromSystem // // Synopsis: Run the action as an exe or other shell object on the choosen desktop // // Arguments: CShellDll* pShellDll - pointer to the link to shell32.dll // LPTSTR pszDesktop - name of the desktop to execute the exe on // DWORD dwLoadType - location from which to load the exe // // Returns: HANDLE - The action Process handle, for Win32 only // // History: v-vijayb Created 07/19/99 // nickball Removed fSecurity 07/27/99 // //+---------------------------------------------------------------------------- HANDLE CAction::RunAsExeFromSystem(CShellDll* pShellDll, LPTSTR pszDesktop, DWORD dwLoadType) { STARTUPINFO StartupInfo = {0}; PROCESS_INFORMATION ProcessInfo = {0}; LPWSTR pszwFullPath = NULL; LPWSTR pszwCommandLine = NULL; MYDBGASSERT(OS_NT); StartupInfo.cb = sizeof(StartupInfo); if (pszDesktop) { StartupInfo.lpDesktop = pszDesktop; StartupInfo.wShowWindow = SW_SHOW; } // // Use an explicit path to the modules to be launched, this // prevents CreateProcess from picking something up on the path. // if (!GetLoadDirWithAlloc(dwLoadType, &pszwFullPath)) { CMASSERTMSG(FALSE, TEXT("CAction::RunAsExeFromSystem -- GetLoadDirWithAlloc Failed.")); goto Cleanup; } pszwCommandLine = CmStrCpyAlloc(m_pszProgram); if (NULL == pszwCommandLine) { CMASSERTMSG(FALSE, TEXT("CAction::RunAsExeFromSystem -- CmStrCpyAlloc Failed.")); goto Cleanup; } // // Add parameters // if (NULL == CmStrCatAlloc(&pszwCommandLine, TEXT(" "))) { goto Cleanup; } if (NULL == CmStrCatAlloc(&pszwCommandLine, m_pszParams)) { goto Cleanup; } CMTRACE1(TEXT("RunAsExeFromSystem/CreateProcess() - Launching %s"), pszwCommandLine); // // Launch the modules, this could be CreateProcessU but it isn't necessary as this only runs on NT // if (NULL == CreateProcess(pszwFullPath, pszwCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)) { CMTRACE2(TEXT("RunAsExeFromSystem() CreateProcess() of %s failed, GLE=%u."), pszwCommandLine, GetLastError()); ProcessInfo.hProcess = NULL; ProcessInfo.hThread = NULL; } Cleanup: if (ProcessInfo.hThread) { CloseHandle(ProcessInfo.hThread); } CmFree(pszwFullPath); CmFree(pszwCommandLine); return ProcessInfo.hProcess; } //+---------------------------------------------------------------------------- // // Function: CAction::ExpandMacros // // Synopsis: Replace the %xxxxx% in command line with the corresponding value // // Arguments: ArgsStruct *pArgs - // // Returns: Nothing // // History: fengsun Created Header 11/14/97 // //+---------------------------------------------------------------------------- void CAction::ExpandMacros(ArgsStruct *pArgs) { MYDBGASSERT(pArgs); LPTSTR pszCurr = m_pszParams; BOOL bValidPropertyName; while (*pszCurr) { if (*pszCurr == TEXT('%')) { LPTSTR pszNextPercent = CmStrchr(pszCurr + 1, TEXT('%')); if (pszNextPercent) { LPTSTR pszTmp = (LPTSTR) CmMalloc((DWORD)((pszNextPercent-pszCurr))*sizeof(TCHAR)); if (pszTmp) { CopyMemory(pszTmp,pszCurr+1,(pszNextPercent-pszCurr-1)*sizeof(TCHAR)); // // Get the value from name // LPTSTR pszMid = pArgs->GetProperty(pszTmp, &bValidPropertyName); // // If the property does not exist, use "NULL" // if (pszMid == NULL) { pszMid = CmStrCpyAlloc(TEXT("NULL")); } else if (pszMid[0] == TEXT('\0')) { CmFree(pszMid); pszMid = CmStrCpyAlloc(TEXT("NULL")); } else if ( (lstrcmpiU(pszTmp,TEXT("Profile")) == 0) || CmStrchr(pszMid, TEXT(' ')) != NULL) { // // If the name is %Profile% or the value has a space in it, // Put the string in double quote // LPTSTR pszValueInQuote = (LPTSTR)CmMalloc((lstrlenU(pszMid)+3)*sizeof(pszMid[0])); if (pszValueInQuote) { lstrcpyU(pszValueInQuote, TEXT("\"")); lstrcatU(pszValueInQuote, pszMid); lstrcatU(pszValueInQuote, TEXT("\"")); CmFree(pszMid); pszMid = pszValueInQuote; } else { CMTRACE1(TEXT("ExpandMacros() malloc failed, can't put string in double quotes, GLE=%u."), GetLastError()); } } // // if bValidPropertyName is FALSE then leave untouched. // if (FALSE == bValidPropertyName) { pszCurr = pszNextPercent + 1; } else { // // Replace %xxxx% with the value // DWORD dwLenPre = (DWORD)(pszCurr - m_pszParams); DWORD dwLenMid = lstrlenU(pszMid); DWORD dwLenPost = lstrlenU(pszNextPercent+1); CmFree(pszTmp); pszTmp = m_pszParams; m_pszParams = (LPTSTR) CmMalloc((dwLenPre + dwLenMid + dwLenPost + 1)*sizeof(TCHAR)); if (m_pszParams) { CopyMemory(m_pszParams, pszTmp, dwLenPre*sizeof(TCHAR)); // before % lstrcatU(m_pszParams, pszMid); //append value lstrcatU(m_pszParams, pszNextPercent+1); // after % pszCurr = m_pszParams + dwLenPre + dwLenMid; } else { // we're out of memory CMTRACE1(TEXT("ExpandMacros() malloc failed, can't strip off %% signs, GLE=%u."), GetLastError()); m_pszParams = pszTmp; } } CmFree(pszMid); } CmFree(pszTmp); } else { pszCurr++; } } else { pszCurr++; } } } #ifdef DEBUG //+---------------------------------------------------------------------------- // // Function: CAction::AssertValid // // Synopsis: For debug purpose only, assert the connection object is valid // // Arguments: None // // Returns: Nothing // // History: Created Header 2/12/98 // //+---------------------------------------------------------------------------- void CAction::AssertValid() const { MYDBGASSERT(m_pszProgram && m_pszProgram[0]); MYDBGASSERT(m_fIsDll == TRUE || m_fIsDll == FALSE); } #endif //+---------------------------------------------------------------------------- // // Function: CAction::ExpandEnvironmentStrings // // Synopsis: Utility fn to expand environment variables in the given string // // Arguments: ppsz - ptr to string (usually member variable) // // Returns: Nothing // // History: SumitC Created 29-Feb-2000 // //+---------------------------------------------------------------------------- void CAction::ExpandEnvironmentStrings(LPTSTR * ppsz) { DWORD cLen; MYDBGASSERT(*ppsz); // // find out how much memory we need to allocate // cLen = ExpandEnvironmentStringsU(*ppsz, NULL, 0); if (cLen) { LPTSTR pszTemp = (LPTSTR) CmMalloc((cLen + 1) * sizeof(TCHAR)); if (pszTemp) { DWORD cLen2 = ExpandEnvironmentStringsU(*ppsz, pszTemp, cLen); MYDBGASSERT(cLen == cLen2); if (cLen2) { CmFree(*ppsz); *ppsz = pszTemp; } } } } //+---------------------------------------------------------------------------- // // Function: CAction::IsAllowed // // Synopsis: checks Registry to see if a command is allowed to run // // Arguments: _ArgsStruct *pArgs - Ptr to global args struct // LPDWORD lpdwLoadType - Ptr to DWORD to be filled with load type // // Returns: TRUE if action is allowed @ this time // // Notes: Checks SOFTWARE\Microsoft\Connection Manager\ // Under which you will have the Values for each command // 0 - system32 directory // 1 - profile directory // History: v-vijayb Created Header 7/20/99 // //+---------------------------------------------------------------------------- BOOL CAction::IsAllowed(_ArgsStruct *pArgs, LPDWORD lpdwLoadType) { return IsActionEnabled(m_pszProgram, pArgs->szServiceName, pArgs->piniService->GetFile(), lpdwLoadType); } //+---------------------------------------------------------------------------- // // Function: CAction::RunConnectActionForCurrentConnection // // Synopsis: This function compares the flags value of the connect action // with the current connection type (from pArgs->GetTypeOfConnection). // It returns TRUE if the connect action should be run for this type // and FALSE if the connect action should be skipped. // // Arguments: _ArgsStruct *pArgs - Ptr to global args struct // // Returns: TRUE if action should be executed // // History: quintinb Created 04/20/00 // //+---------------------------------------------------------------------------- BOOL CAction::RunConnectActionForCurrentConnection(_ArgsStruct *pArgs) { BOOL bReturn = TRUE; DWORD dwType = pArgs->GetTypeOfConnection(); if (DIAL_UP_CONNECTION == dwType) { // // Don't run direct only or tunnel connect actions // on a dialup connection. // if ((m_dwFlags & DIRECT_ONLY) || (m_dwFlags & ALL_TUNNEL)) { bReturn = FALSE; } } else if (DIRECT_CONNECTION == dwType) { // // Don't run dialup only or dialup connect actions // on a direct connection. // if ((m_dwFlags & DIALUP_ONLY) || (m_dwFlags & ALL_DIALUP)) { bReturn = FALSE; } } else if (DOUBLE_DIAL_CONNECTION == dwType) { // // Don't run dialup only or dialup connect actions // on a direct connection. // if ((m_dwFlags & DIALUP_ONLY) || (m_dwFlags & DIRECT_ONLY)) { bReturn = FALSE; } } else { CMASSERTMSG(FALSE, TEXT("CActionList::Run -- unknown connection type, skipping action")); bReturn = FALSE; } return bReturn; }