mirror of
https://github.com/microsoft/Microsoft-3D-Movie-Maker.git
synced 2024-11-22 10:22:40 +01:00
447 lines
13 KiB
C++
447 lines
13 KiB
C++
/* Copyright (c) Microsoft Corporation.
|
|
Licensed under the MIT License. */
|
|
|
|
/******************************************************************************
|
|
|
|
@doc AUTORUN
|
|
|
|
@mod AUTORUN.CPP |
|
|
|
|
<cp> Copyright 1995 Microsoft Corporation - All rights reserved
|
|
|
|
*******************************************************************************
|
|
|
|
Description: This module contains functions to implement the autorun
|
|
stub as documented in autorun.doc. Flow chart as follows:
|
|
|
|
32bit - NO --> Run Setup
|
|
installed?
|
|
|
|
|
YES
|
|
|
|
|
running? - YES -> Quit
|
|
|
|
|
NO
|
|
|
|
|
Run 32bit.
|
|
|
|
Current Owner: *****
|
|
|
|
*******************************************************************************
|
|
|
|
Known bugs: None
|
|
|
|
*******************************************************************************
|
|
|
|
How it could be Improved:
|
|
|
|
*******************************************************************************
|
|
|
|
Revision History:
|
|
|
|
06/27/95 ***** Created
|
|
|
|
******************************************************************************/
|
|
#include <windows.h>
|
|
#include "tlhelp32.h" // in the sdk/h directory
|
|
#include "resource.h"
|
|
|
|
typedef struct
|
|
{
|
|
HINSTANCE hInstance; // Instance of launched app
|
|
HTASK hTask; // Task of launched app
|
|
HWND hWnd; // Window of launched app
|
|
} LINKEDAPP, FAR *LPLINKEDAPP;
|
|
|
|
|
|
typedef BOOL (WINAPI *MODULEWALK) (HANDLE hSnapshot, LPMODULEENTRY32 lpme);
|
|
typedef BOOL (WINAPI *THREADWALK) (HANDLE hSnapshot, LPTHREADENTRY32 lpte);
|
|
typedef BOOL (WINAPI *PROCESSWALK) (HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
|
|
typedef HANDLE (WINAPI *CREATESNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID);
|
|
|
|
CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL; // pointer to CreateToolhelp32Snapshot function
|
|
PROCESSWALK pProcess32First = NULL; // pointer to Process32First function
|
|
PROCESSWALK pProcess32Next = NULL; // pointer to Process32Next function
|
|
MODULEWALK pModule32First = NULL; // pointer to Module32First function
|
|
MODULEWALK pModule32Next = NULL; // pointer to Module32Next function
|
|
THREADWALK pThread32First = NULL;
|
|
THREADWALK pThread32Next = NULL;
|
|
|
|
BOOL GetThreadProcess(DWORD, DWORD, LPPROCESSENTRY32, DWORD);
|
|
BOOL GetProcessModule(DWORD, DWORD, LPMODULEENTRY32, DWORD);
|
|
|
|
|
|
// taken from the pview95 code in the sdk32. enumerates Win32 modules
|
|
|
|
BOOL GetProcessModule(DWORD dwPID, DWORD dwModuleID, LPMODULEENTRY32 lpMe32, DWORD cbMe32)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
BOOL bFound = FALSE;
|
|
HANDLE hModuleSnap = NULL;
|
|
MODULEENTRY32 me32 = {0};
|
|
|
|
// Take a snapshot of all modules in the specified process.
|
|
|
|
hModuleSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
|
|
|
|
if (hModuleSnap == (HANDLE)-1)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
// Size of the MODULEENTRY32 structure must be initialized before use!
|
|
|
|
me32.dwSize = sizeof(MODULEENTRY32);
|
|
|
|
// Walk the module list of the process and find the module we are
|
|
// interested in. Then, copy the information to the buffer pointed to
|
|
// by lpMe32 so that we can return it to the caller.
|
|
|
|
if (pModule32First(hModuleSnap, &me32))
|
|
{
|
|
do
|
|
{
|
|
if (me32.th32ModuleID == dwModuleID)
|
|
{
|
|
CopyMemory (lpMe32, &me32, cbMe32);
|
|
bFound = TRUE;
|
|
}
|
|
} while (!bFound && pModule32Next(hModuleSnap, &me32));
|
|
|
|
bRet = bFound; // If this sets bRet to FALSE, then dwModuleID
|
|
// no longer exists in the specified process.
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE; // Couldn't walk module list.
|
|
}
|
|
|
|
// Don't forget to clean up the snapshot object...
|
|
|
|
CloseHandle (hModuleSnap);
|
|
|
|
return (bRet);
|
|
}
|
|
|
|
BOOL GetThreadProcess(DWORD dwThreadID, DWORD dwPID, LPPROCESSENTRY32 lpPe32, DWORD cbPe32)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
BOOL bFound = FALSE;
|
|
HANDLE hProcessSnap = NULL;
|
|
PROCESSENTRY32 pe32 = {0};
|
|
|
|
// Take a snapshot of all processes in the system.
|
|
|
|
hProcessSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
|
|
if (hProcessSnap == (HANDLE)-1)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
// Size of the PROCESSENTRY32 structure must be initialized before use!
|
|
|
|
pe32.dwSize = sizeof(PROCESSENTRY32);
|
|
|
|
// Walk the process list and find the process we are
|
|
// interested in. Then, copy the information to the buffer pointed to
|
|
// by lpPe32 so that we can return it to the caller.
|
|
|
|
if (pProcess32First(hProcessSnap, &pe32))
|
|
{
|
|
do
|
|
{
|
|
if (pe32.th32ProcessID == dwPID)
|
|
{
|
|
CopyMemory (lpPe32, &pe32, cbPe32);
|
|
bFound = TRUE;
|
|
}
|
|
} while (!bFound && pProcess32Next(hProcessSnap, &pe32));
|
|
|
|
bRet = bFound; // If this sets bRet to FALSE, then dwPID
|
|
// no longer exists in the specified process.
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE; // Couldn't walk process list.
|
|
}
|
|
|
|
// Don't forget to clean up the snapshot object...
|
|
|
|
CloseHandle (hProcessSnap);
|
|
|
|
return (bRet);
|
|
}
|
|
|
|
/******************************************************************************
|
|
|
|
@func BOOL | EnumTaskWndProc |
|
|
|
|
This callback function finds the first top-level window of a particular
|
|
task.
|
|
|
|
@parm HWND | hWnd | Window to examine.
|
|
|
|
@parm LPARAM | lParam | Pointer to a LINKEDAPP structure containing the
|
|
module instance.
|
|
|
|
@rdesc Returns true (always finds the first top-level window).
|
|
|
|
******************************************************************************/
|
|
|
|
BOOL CALLBACK EnumTaskWndProc(HWND hWnd, LPARAM lParam)
|
|
{
|
|
LPLINKEDAPP lpla;
|
|
|
|
// This is needed because some apps (i.e. MSWord) have other, invisible top-level windows (God only knows what for!)
|
|
if (!IsWindowVisible(hWnd))
|
|
return TRUE;
|
|
|
|
lpla = (LPLINKEDAPP) lParam;
|
|
lpla->hWnd = hWnd;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL IsAppRunning(LPSTR lpszPath, LPLINKEDAPP lpla)
|
|
{
|
|
BOOL fRet = FALSE; // return value
|
|
HANDLE hKernel32 = NULL;
|
|
|
|
hKernel32 = GetModuleHandle("KERNEL32.DLL");
|
|
|
|
if (hKernel32)
|
|
{
|
|
DWORD dwExitCode;
|
|
HANDLE hProcessSnap = NULL; // snapshot of all processes
|
|
PROCESSENTRY32 pe32 = { 0 };
|
|
THREADENTRY32 te32 = { 0 };
|
|
|
|
pCreateToolhelp32Snapshot = (CREATESNAPSHOT)GetProcAddress((HMODULE)hKernel32, "CreateToolhelp32Snapshot");
|
|
pProcess32First = (PROCESSWALK) GetProcAddress((HMODULE)hKernel32, "Process32First");
|
|
pProcess32Next = (PROCESSWALK) GetProcAddress((HMODULE)hKernel32, "Process32Next");
|
|
pModule32First = (MODULEWALK) GetProcAddress((HMODULE)hKernel32, "Module32First");
|
|
pModule32Next = (MODULEWALK) GetProcAddress((HMODULE)hKernel32, "Module32Next");
|
|
pThread32First = (THREADWALK) GetProcAddress((HMODULE)hKernel32, "Thread32First");
|
|
pThread32Next = (THREADWALK) GetProcAddress((HMODULE)hKernel32, "Thread32Next");
|
|
|
|
// all function pointers are valid
|
|
|
|
if (pCreateToolhelp32Snapshot && pProcess32First && pProcess32Next &&
|
|
pModule32First && pModule32Next && pThread32First && pThread32Next )
|
|
{
|
|
if (!IsWindow(lpla->hWnd) || // is there a window
|
|
!(GetExitCodeProcess(lpla->hTask, &dwExitCode) && // can we get the process status
|
|
dwExitCode == STILL_ACTIVE) || // and is the process still active
|
|
GetWindowTask(lpla->hWnd) != lpla->hTask) // is this the same task
|
|
{
|
|
// now we have to find another instance of this process, if one exists
|
|
// Take a snapshot of all threads currently in the system.
|
|
|
|
hProcessSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
|
|
|
if (hProcessSnap != (HANDLE)-1)
|
|
{
|
|
// Size of the PROCESSENTRY32 structure must be filled out before use.
|
|
|
|
pe32.dwSize = sizeof(PROCESSENTRY32);
|
|
te32.dwSize = sizeof(THREADENTRY32);
|
|
|
|
// Walk the snapshot of processes and for each process, get info
|
|
|
|
if (pThread32First(hProcessSnap, &te32))
|
|
{
|
|
MODULEENTRY32 me32;
|
|
|
|
do
|
|
{
|
|
GetThreadProcess(te32.th32ThreadID, te32.th32OwnerProcessID, &pe32, sizeof(PROCESSENTRY32));
|
|
GetProcessModule(pe32.th32ProcessID, pe32.th32ModuleID, &me32, sizeof(MODULEENTRY32));
|
|
|
|
if (lstrcmpi((LPSTR)me32.szExePath, lpszPath) == 0)
|
|
{
|
|
// found it!! Now need to fill in lpla struct
|
|
lpla->hWnd = NULL;
|
|
EnumThreadWindows(te32.th32ThreadID, (WNDENUMPROC) EnumTaskWndProc, (LPARAM)lpla);
|
|
fRet = TRUE;
|
|
}
|
|
} while (!fRet && pThread32Next(hProcessSnap, &te32));
|
|
|
|
CloseHandle (hProcessSnap);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
#define INI_MAX_ENTRY 120
|
|
|
|
BOOL FGetExePath(HINSTANCE hInstance, int isz, char rgchExePath[])
|
|
{
|
|
char rgchSubKey[INI_MAX_ENTRY];
|
|
char rgchValue[INI_MAX_ENTRY];
|
|
HKEY hkResult;
|
|
DWORD dwType = REG_SZ, dwSize = INI_MAX_ENTRY;
|
|
long cch;
|
|
|
|
if (!LoadString(hInstance, isz, rgchSubKey, INI_MAX_ENTRY))
|
|
return FALSE;
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, rgchSubKey, 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
|
|
return FALSE;
|
|
|
|
if (!LoadString(hInstance, isz+1, rgchValue, INI_MAX_ENTRY))
|
|
return FALSE;
|
|
rgchExePath[0] = '\0';
|
|
|
|
RegQueryValueEx(hkResult, rgchValue, 0, &dwType,
|
|
(unsigned char *)rgchExePath, &dwSize);
|
|
|
|
if (rgchExePath[0] == '\0')
|
|
return FALSE;
|
|
|
|
if (isz == STBL_APPINSTALLKEY)
|
|
{
|
|
cch = strlen(rgchExePath);
|
|
|
|
if (!LoadString(hInstance, isz+2, rgchValue, INI_MAX_ENTRY))
|
|
return FALSE;
|
|
|
|
RegQueryValueEx(hkResult, rgchValue, 0, &dwType,
|
|
(unsigned char *)(&rgchExePath[cch]), &dwSize);
|
|
|
|
if (rgchExePath[cch] == '\0')
|
|
return FALSE;
|
|
|
|
cch = strlen(rgchExePath);
|
|
|
|
if (!LoadString(hInstance, STBL_APPINSTALLNAME, &rgchExePath[cch],
|
|
INI_MAX_ENTRY - cch))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
WinMain
|
|
***************************************************************************/
|
|
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
|
{
|
|
char rgchPath [INI_MAX_ENTRY * 2];
|
|
int isz;
|
|
BOOL fRunSetup = FALSE;
|
|
char rgchSetupClass[INI_MAX_ENTRY];
|
|
|
|
|
|
if (!LoadString(hInstance, STBL_SETUPCLASS, rgchSetupClass, INI_MAX_ENTRY))
|
|
return FALSE;
|
|
|
|
if (FindWindow(rgchSetupClass, NULL))
|
|
return 1;
|
|
|
|
isz = STBL_APPPATHKEY;
|
|
while (!fRunSetup)
|
|
{
|
|
if (FGetExePath(hInstance, isz, rgchPath))
|
|
{
|
|
LINKEDAPP la;
|
|
|
|
la.hInstance = NULL;
|
|
la.hTask = NULL;
|
|
la.hWnd = NULL;
|
|
|
|
if (IsAppRunning(rgchPath, &la))
|
|
{
|
|
if (IsIconic(la.hWnd))
|
|
ShowWindow(la.hWnd, SW_RESTORE);
|
|
|
|
SetForegroundWindow(la.hWnd);
|
|
|
|
break;
|
|
}
|
|
else // Not running, so run it
|
|
{
|
|
PROCESS_INFORMATION pi;
|
|
STARTUPINFO si;
|
|
|
|
si.cb = sizeof(STARTUPINFO);
|
|
si.lpReserved = NULL;
|
|
si.lpDesktop = NULL;
|
|
si.lpTitle = NULL;
|
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
|
si.wShowWindow = SW_SHOWDEFAULT;
|
|
si.cbReserved2 = 0;
|
|
si.lpReserved2 = NULL;
|
|
|
|
if (CreateProcess(rgchPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (isz == STBL_APPPATHKEY)
|
|
isz = STBL_APPINSTALLKEY;
|
|
else
|
|
fRunSetup = TRUE;
|
|
}
|
|
|
|
if (fRunSetup) // App path not found or CreateProcess failed, Not installed
|
|
{
|
|
char rgchSetupPath[_MAX_PATH];
|
|
char rgchSetupFName[_MAX_FNAME];
|
|
char *pch;
|
|
int i;
|
|
|
|
if (!LoadString(hInstance, STBL_SETUPFNAME, rgchSetupFName, _MAX_FNAME)) return FALSE;
|
|
|
|
/* Relative path? */
|
|
if (rgchSetupFName[0] == '.')
|
|
{
|
|
GetModuleFileName(NULL, rgchSetupPath, _MAX_PATH);
|
|
|
|
pch = strchr(rgchSetupPath, ' ');
|
|
if (NULL != pch)
|
|
{
|
|
*pch = '\0';
|
|
}
|
|
|
|
i = strlen(rgchSetupPath);
|
|
pch = rgchSetupPath + i;
|
|
|
|
while (pch != rgchSetupPath && *pch != '\\')
|
|
pch--;
|
|
|
|
*(pch+1) = '\0';
|
|
|
|
strcat(rgchSetupPath, rgchSetupFName);
|
|
}
|
|
else
|
|
strcpy(rgchSetupPath, rgchSetupFName);
|
|
|
|
PROCESS_INFORMATION pi;
|
|
STARTUPINFO si;
|
|
|
|
si.cb = sizeof(STARTUPINFO);
|
|
si.lpReserved = NULL;
|
|
si.lpDesktop = NULL;
|
|
si.lpTitle = NULL;
|
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
|
si.wShowWindow = SW_SHOWDEFAULT;
|
|
si.cbReserved2 = 0;
|
|
si.lpReserved2 = NULL;
|
|
|
|
// Start setup
|
|
CreateProcess(rgchSetupPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
|
|
}
|
|
|
|
return 1;
|
|
}
|