windows-nt/Source/XPSP1/NT/printscan/wia/setup/redist/wiasetup.c

975 lines
26 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include "precomp.h"
#include "resource.h"
#ifdef DEBUG
#define TRACE(x) Trace x
#else
#define TRACE(x) Trace x
#endif
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof((x)[0]))
static const CHAR __filename[] = __FILE__;
#define CHECK(x) do { if(!(x)) \
{ CHAR ErrorText[80]; GetErrorText(GetLastError(), ErrorText, 80); \
TRACE((_T("%hs(%d): %hs failed. Error: %hs\n"), \
__filename, __LINE__, #x, ErrorText)); \
goto Cleanup; } } while(0)
#define CHECK2(x, y) do { if(!(x)) \
{ CHAR ErrorText[80]; GetErrorText(GetLastError(), ErrorText, 80); \
TRACE((_T("%hs(%d): %hs ("), __filename, __LINE__, #x)); \
TRACE((y)); \
TRACE((_T(") failed. Error: %hs\n"), ErrorText)); \
goto Cleanup; } } while(0)
#define CHECK_SUCCESS(x) do { LONG lr; lr = (x); if(lr != ERROR_SUCCESS) \
{ CHAR ErrorText[80]; GetErrorText(lr, ErrorText, 80); \
TRACE((_T("%hs(%d): %s failed. Error: %hs\n"), \
__filename, __LINE__, #x, ErrorText)); \
goto Cleanup; } } while(0)
void Trace(LPTSTR fmt, ...);
void GetErrorText(DWORD dwError, CHAR *ErrorText, UINT maxChar);
void MakeFileName(TCHAR *FileName, TCHAR *Directory, TCHAR *BaseName);
BOOL MyDeleteService(TCHAR *ServiceName);
BOOL MyMoveFile(TCHAR *File, TCHAR *SourceDir, TCHAR *DestinationDir);
BOOL MyDeleteDirectory(TCHAR *Directory);
BOOL MyRegDeleteKey(HKEY hKey, TCHAR *subkey);
BOOL RegisterServer32(TCHAR *Module, TCHAR *Options);
BOOL IsFirstFileOlderThanSecond(TCHAR *Source, TCHAR *Destination);
#define REGKEY_SVCHOST _T("Software\\Microsoft\\Windows NT\\CurrentVersion\\SvcHost")
#define REGKEY_STISVC_PARAMETERS _T("SYSTEM\\CurrentControlSet\\Services\\StiSvc\\Parameters")
#define STIBACKUP_DIR _T("%SystemRoot%\\System32\\StiBackup.bak")
#define WINDOWS_DIR _T("%SystemRoot%")
#define TWAIN_DIR _T("%SystemRoot%\\twain_32")
#define SYSTEM32_DIR _T("%SystemRoot%\\System32")
#define DRIVERS_DIR _T("%SystemRoot%\\System32\\Drivers")
#define INF_DIR _T("%SystemRoot%\\Inf")
TCHAR WindowsDirectory[MAX_PATH];
TCHAR TwainDirectory[MAX_PATH];
TCHAR SystemDirectory[MAX_PATH];
TCHAR DriversDirectory[MAX_PATH];
TCHAR InfDirectory[MAX_PATH];
TCHAR szModuleName[] = _T("wiasetup.dll");
typedef struct FileTableEntry {
TCHAR *FileName;
TCHAR *Location;
BOOL bRegister;
BOOL bIgnore;
} FileTableEntry;
FileTableEntry FileTable[] = {
// { _T("camocx.dll"), SystemDirectory, TRUE, FALSE },
// { _T("cropview.dll"), SystemDirectory, TRUE, FALSE },
// { _T("extend.dll"), SystemDirectory, FALSE, FALSE },
{ _T("scsiscan.sys"), DriversDirectory, FALSE, FALSE },
{ _T("sti.dll"), SystemDirectory, TRUE, FALSE },
{ _T("sti_ci.dll"), SystemDirectory, TRUE, FALSE },
{ _T("sticpl.cpl"), SystemDirectory, FALSE, FALSE },
{ _T("stimon.exe"), SystemDirectory, FALSE, FALSE },
{ _T("stisvc.exe"), SystemDirectory, FALSE, FALSE },
{ _T("twain_32.dll"), WindowsDirectory, FALSE, FALSE },
{ _T("twunk_32.exe"), WindowsDirectory, FALSE, FALSE },
{ _T("twunk_16.exe"), WindowsDirectory, FALSE, FALSE },
{ _T("wiatwain.ds"), TwainDirectory, FALSE, FALSE },
{ _T("usbscan.sys"), DriversDirectory, FALSE, FALSE },
// { _T("wiaacmgr.exe"), SystemDirectory, FALSE, FALSE },
{ _T("wiadefui.dll"), SystemDirectory, TRUE, FALSE },
// { _T("wiadenum.dll"), SystemDirectory, TRUE, FALSE },
{ _T("wiadss.dll"), SystemDirectory, TRUE, FALSE },
{ _T("wiafbdrv.dll"), SystemDirectory, TRUE, FALSE },
// { _T("wiascanx.dll"), SystemDirectory, TRUE, FALSE },
// { _T("wiascr.dll"), SystemDirectory, TRUE, FALSE },
// { _T("wiascr.tlb"), SystemDirectory, FALSE, FALSE },
{ _T("wiaservc.dll"), SystemDirectory, TRUE, FALSE },
{ _T("wiasf.ax"), SystemDirectory, TRUE, FALSE },
{ _T("wiashext.dll"), SystemDirectory, TRUE, FALSE },
// { _T("wiastatd.dll"), SystemDirectory, FALSE, FALSE },
// { _T("wiatscan.dll"), SystemDirectory, FALSE, FALSE },
{ _T("wiavusd.dll"), SystemDirectory, TRUE, FALSE },
{ _T("sti.inf"), InfDirectory, FALSE, FALSE },
{ NULL, NULL, FALSE, FALSE }
};
BOOL __stdcall InstallWia(void);
BOOL __stdcall RemoveWia(void);
UINT CALLBACK wsIterateCabinetCallback(PVOID, UINT, UINT, UINT);
BOOL InstallFileTable(FileTableEntry *pTable, TCHAR *DirInstallFrom, TCHAR *BackupDir);
BOOL InstallWiaService(void);
BOOL InstallStiService(void);
#if 0
#ifdef UNICODE
#define WinMain wWinMain
#endif
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPTSTR lpCmd, int nShow)
{
if((lpCmd[0] == _T('-') || lpCmd[0] == _T('/')) &&
(lpCmd[1] == _T('u') || lpCmd[0] == _T('U')))
{
CHECK(RemoveWia());
}
else
{
CHECK(InstallWia());
}
Cleanup:
return 0;
}
#endif
BOOL __stdcall InstallWia(void)
{
BOOL success = FALSE;
HINSTANCE hCi = NULL;
TCHAR StiBackupDirectory[MAX_PATH];
TCHAR TempDirectory[MAX_PATH];
TCHAR WiaCabFile[MAX_PATH];
TCHAR path[MAX_PATH];
DWORD dwAttributes;
int i;
HMODULE hModule;
BOOL CreatedBackupDirectory = FALSE;
BOOL CreatedTempDirectory = FALSE;
BOOL InstalledWiaEnvironment = FALSE;
OSVERSIONINFOEX osv;
ZeroMemory(&osv, sizeof(osv));
osv.dwOSVersionInfoSize = sizeof(osv);
osv.dwMajorVersion = 5;
// make sure we have NT5 or better
CHECK(VerifyVersionInfo(&osv, VER_MAJORVERSION, VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL)));
//
// Get system paths
//
CHECK(ExpandEnvironmentStrings(WINDOWS_DIR, WindowsDirectory, MAX_PATH));
CHECK(ExpandEnvironmentStrings(TWAIN_DIR, TwainDirectory, MAX_PATH));
CHECK(ExpandEnvironmentStrings(SYSTEM32_DIR, SystemDirectory, MAX_PATH));
CHECK(ExpandEnvironmentStrings(DRIVERS_DIR, DriversDirectory, MAX_PATH));
CHECK(ExpandEnvironmentStrings(INF_DIR, InfDirectory, MAX_PATH));
CHECK(ExpandEnvironmentStrings(STIBACKUP_DIR, StiBackupDirectory, MAX_PATH));
// Get our module file name
hModule = GetModuleHandle(szModuleName);
CHECK(hModule != NULL);
CHECK(GetModuleFileName(hModule, WiaCabFile, MAX_PATH));
//
// Create backup directory, if it does not already exist
//
dwAttributes = GetFileAttributes(StiBackupDirectory);
if(dwAttributes == -1)
{
CHECK(CreateDirectory(StiBackupDirectory, NULL));
}
CreatedBackupDirectory = TRUE;
MakeFileName(path, StiBackupDirectory, _T("wiasetup.dll"));
CHECK(CopyFile(WiaCabFile, path, FALSE));
// Find the last "\"
for(i = 0; i < MAX_PATH && WiaCabFile[i] != _T('\0'); i++)
;
while(i > 0 && WiaCabFile[i] != _T('\\'))
i--;
CHECK(WiaCabFile[i] == _T('\\'));
// Append cabinet name afer the last backslash
lstrcpy(WiaCabFile + i, _T("\\wiasetup.cab"));
// Verify that CAB file exist
CHECK((dwAttributes = GetFileAttributes(WiaCabFile)) != -1);
// Generate temp directory name and create temp directory
CHECK(GetTempPath(MAX_PATH, path));
CHECK(GetTempFileName(path, _T("wsetup"), 0, TempDirectory));
CHECK(DeleteFile(TempDirectory));
CHECK(CreateDirectory(TempDirectory, NULL));
CreatedTempDirectory = TRUE;
//
// Extract our .CAB file into it
//
CHECK(SetupIterateCabinet(WiaCabFile, 0, wsIterateCabinetCallback, TempDirectory));
//
// Remove STISVC service
//
CHECK(MyDeleteService(_T("stisvc")));
//
// Install and register all the files
//
CHECK(InstallFileTable(FileTable, TempDirectory, StiBackupDirectory));
InstalledWiaEnvironment = TRUE;
CHECK(InstallWiaService());
//
// Mark success
//
success = TRUE;
Cleanup:
if(CreatedTempDirectory) MyDeleteDirectory(TempDirectory);
if(!success)
{
if(InstalledWiaEnvironment) RemoveWia();
}
return success;
}
BOOL __stdcall RemoveWia(void)
{
BOOL success = FALSE;
TCHAR StiBackupDirectory[MAX_PATH];
//
// Get system paths
//
CHECK(ExpandEnvironmentStrings(WINDOWS_DIR, WindowsDirectory, MAX_PATH));
CHECK(ExpandEnvironmentStrings(TWAIN_DIR, TwainDirectory, MAX_PATH));
CHECK(ExpandEnvironmentStrings(SYSTEM32_DIR, SystemDirectory, MAX_PATH));
CHECK(ExpandEnvironmentStrings(DRIVERS_DIR, DriversDirectory, MAX_PATH));
CHECK(ExpandEnvironmentStrings(STIBACKUP_DIR, StiBackupDirectory, MAX_PATH));
CHECK(MyDeleteService(_T("stisvc")));
CHECK(InstallFileTable(FileTable, StiBackupDirectory, NULL));
CHECK(InstallStiService());
CHECK(MyDeleteDirectory(StiBackupDirectory));
success = TRUE;
Cleanup:
return success;
}
//
// This is called by SetupIterateCabinet for each file in cabinet
//
UINT CALLBACK
wsIterateCabinetCallback(PVOID pContext, UINT Notification,
UINT Param1, UINT Param2)
{
UINT result = NO_ERROR;
TCHAR *TargetDir = (TCHAR *)pContext;
FILE_IN_CABINET_INFO *pInfo = NULL;
FILEPATHS *pFilePaths = NULL;
switch(Notification)
{
case SPFILENOTIFY_FILEINCABINET:
pInfo = (FILE_IN_CABINET_INFO *)Param1;
MakeFileName(pInfo->FullTargetName, TargetDir, (TCHAR *)pInfo->NameInCabinet);
result = FILEOP_DOIT; // Extract the file.
break;
case SPFILENOTIFY_FILEEXTRACTED:
pFilePaths = (FILEPATHS *)Param1;
result = NO_ERROR;
break;
case SPFILENOTIFY_NEEDNEWCABINET: // Unexpected.
result = NO_ERROR;
break;
}
return result;
}
BOOL
InstallFileTable(
FileTableEntry *pTable,
TCHAR *DirInstallFrom,
TCHAR *BackupDir)
/*++
Performs four passes over the specified file table:
1. Checks version stamp of both source and destination files
and marks older source files to ignore
2. Unregister any old file that needs to be unregistered;
3. Moves every old file into BackupDir and copies any new
file into place from DirInstallFrom;
4. Registers any new file that needs to be registered;
--*/
{
BOOL success = FALSE;
DWORD dwAttributes;
TCHAR Source[MAX_PATH];
TCHAR Destination[MAX_PATH];
HANDLE hSfc = NULL;
FileTableEntry *p;
CHECK(hSfc = SfcConnectToServer(NULL));
//
// Pass 1: mark any older source files to ignore
//
for(p = pTable; p->FileName != NULL; p++)
{
MakeFileName(Source, DirInstallFrom, p->FileName);
dwAttributes = GetFileAttributes(Source);
if(dwAttributes == -1)
{
continue;
}
MakeFileName(Destination, p->Location, p->FileName);
dwAttributes = GetFileAttributes(Destination);
if(dwAttributes == -1)
{
continue;
}
if(IsFirstFileOlderThanSecond(Source, Destination))
{
p->bIgnore = TRUE;
}
}
//
// Pass 2: unregister all DLLs that need registration
//
for(p = pTable; p->FileName != NULL; p++)
{
if(!p->bRegister) continue;
MakeFileName(Destination, p->Location, p->FileName);
dwAttributes = GetFileAttributes(Destination);
if(dwAttributes != -1)
{
CHECK(RegisterServer32(Destination, _T("/u /s")));
}
}
//
// Pass 3: Install all the files
//
for(p = pTable; p->FileName != NULL; p++)
{
//
// Prepare full destination file name, make sure it exists
//
MakeFileName(Destination, p->Location, p->FileName);
dwAttributes = GetFileAttributes(Destination);
if(dwAttributes != -1)
{
//
// If this file is under SFP, make exception
//
if(SfcIsFileProtected(hSfc, Destination))
{
if(SfcFileException(hSfc, Destination,
SFC_ACTION_REMOVED | SFC_ACTION_MODIFIED |
SFC_ACTION_RENAMED_OLD_NAME) != ERROR_SUCCESS)
{
TRACE((_T("InstallFileTable: Failed setting up SFC exception for %s\n"), Destination));
}
}
//
// delete the old file to backup directory
//
CHECK(MyMoveFile(p->FileName, p->Location, BackupDir));
}
//
// Prepare full source file name, make sure it exists
//
MakeFileName(Source, DirInstallFrom, p->FileName);
dwAttributes = GetFileAttributes(Source);
if(dwAttributes != -1)
{
//
// move the new file into place
//
CHECK2(CopyFile(Source, Destination, FALSE), (_T("%s %s"), Source, Destination));
}
}
//
// Pass 4: Register all DLLs that need registration
//
for(p = pTable; p->FileName != NULL; p++)
{
if(!p->bRegister) continue;
MakeFileName(Destination, p->Location, p->FileName);
dwAttributes = GetFileAttributes(Destination);
if(dwAttributes != -1)
{
CHECK(RegisterServer32(Destination, _T("/s")));
}
}
success = TRUE;
Cleanup:
if(hSfc != NULL) SfcClose(hSfc);
return success;
}
BOOL InstallWiaService(void)
{
BOOL success = FALSE;
SC_HANDLE hSvcMgr = NULL;
SC_HANDLE hService = NULL;
SERVICE_STATUS ServiceStatus;
DWORD checkPoint;
TCHAR DisplayName[260];
TCHAR Description[260];
TCHAR mszStiSvc[] = _T("StiSvc\0");
TCHAR szServiceDll[] = _T("%SystemRoot%\\System32\\wiaservc.dll");
HMODULE hModule;
HKEY hKey = NULL;
CHECK(hModule = GetModuleHandle(szModuleName));
CHECK(LoadString(hModule, IDS_WIA_DISPLAY_NAME, DisplayName, ARRAY_LENGTH(DisplayName)));
CHECK(LoadString(hModule, IDS_WIA_DESCRIPTION, Description, ARRAY_LENGTH(Description)));
//
// Add svchost.exe -- specific entries
//
CHECK_SUCCESS(RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGKEY_SVCHOST,
0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL));
CHECK_SUCCESS(RegSetValueEx(hKey, _T("imgsvc"), 0, REG_MULTI_SZ,
(BYTE *)mszStiSvc, (lstrlen(mszStiSvc) + 1) * sizeof(TCHAR)));
CHECK_SUCCESS(RegCloseKey(hKey));
CHECK_SUCCESS(RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGKEY_STISVC_PARAMETERS,
0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL));
CHECK_SUCCESS(RegSetValueEx(hKey, _T("ServiceDll"), 0, REG_EXPAND_SZ,
(BYTE *)szServiceDll, lstrlen(szServiceDll) * sizeof(TCHAR)));
CHECK(hSvcMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS));
CHECK(hService = CreateService(hSvcMgr,
_T("StiSvc"),
DisplayName,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
_T("%SystemRoot%\\System32\\svchost.exe -k imgsvc"),
NULL,
NULL,
_T("RpcSs\0"),
_T("LocalSystem"),
NULL));
success = TRUE;
Cleanup:
if(hService) CloseServiceHandle(hService);
if(hSvcMgr) CloseServiceHandle(hSvcMgr);
if(hKey) RegCloseKey(hKey);
return success;
}
BOOL InstallStiService(void)
{
BOOL success = FALSE;
HINF hInf = INVALID_HANDLE_VALUE;
SC_HANDLE hSvcMgr = NULL;
SC_HANDLE hService = NULL;
TCHAR DisplayName[260];
TCHAR Description[260];
HMODULE hModule;
HKEY hKey = NULL;
LONG lResult;
CHECK(hModule = GetModuleHandle(szModuleName));
CHECK(LoadString(hModule, IDS_STI_DISPLAY_NAME, DisplayName, ARRAY_LENGTH(DisplayName)));
CHECK(LoadString(hModule, IDS_STI_DESCRIPTION, Description, ARRAY_LENGTH(Description)));
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGKEY_SVCHOST,
0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
if(lResult == ERROR_SUCCESS)
{
RegDeleteValue(hKey, _T("imgsvc"));
CHECK_SUCCESS(RegCloseKey(hKey));
hKey = NULL;
}
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGKEY_STISVC_PARAMETERS,
0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL);
if(lResult == ERROR_SUCCESS)
{
RegDeleteValue(hKey, _T("ServiceDll"));
CHECK_SUCCESS(RegCloseKey(hKey));
hKey = NULL;
}
CHECK(hSvcMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS));
CHECK(hService = CreateService(hSvcMgr,
_T("StiSvc"),
DisplayName,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
_T("%SystemRoot%\\System32\\stisvc.exe"),
NULL,
NULL,
_T("RpcSs\0"),
_T("LocalSystem"),
NULL));
hInf = SetupOpenInfFile(_T("sti.inf"), NULL, INF_STYLE_WIN4, NULL);
CHECK(hInf != INVALID_HANDLE_VALUE);
CHECK(SetupInstallFromInfSection(NULL, hInf, _T("ClassInstall32"),
SPINST_REGISTRY, NULL, NULL, 0, NULL, NULL, NULL, NULL));
success = TRUE;
Cleanup:
if(hService) CloseServiceHandle(hService);
if(hSvcMgr) CloseServiceHandle(hSvcMgr);
if(hInf != INVALID_HANDLE_VALUE) SetupCloseInfFile(hInf);
if(hKey) RegCloseKey(hKey);
return TRUE;
}
void GetErrorText(DWORD dwError, CHAR *ErrorText, UINT maxChar)
{
DWORD messageLength, charsToMove;
LPSTR pBuffer = NULL;
messageLength = FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
dwError,
0,
(LPSTR)&pBuffer,
0,
NULL);
charsToMove = min(maxChar, messageLength);
if(charsToMove == 0)
{
wsprintfA(ErrorText, "Unknown error %d (0x%X)", dwError, dwError);
}
else if(charsToMove == maxChar)
{
lstrcpyA(ErrorText, pBuffer);
ErrorText[maxChar - 1] = '\0';
}
else
{
lstrcpyA(ErrorText, pBuffer);
}
if(pBuffer) LocalFree(pBuffer);
}
void Trace(LPTSTR fmt, ...)
{
TCHAR buffer[1024];
TCHAR fileName[MAX_PATH];
HANDLE hFile;
DWORD cbWritten;
va_list a;
va_start(a, fmt);
wvsprintf(buffer, fmt, a);
if(!ExpandEnvironmentStrings(_T("%SystemRoot%\\system32\\wiasetup.log"), fileName, MAX_PATH))
lstrcpy(fileName, _T("wiasetup.log"));
hFile = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, 0, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
#ifdef UNICODE
CHAR bufferA[1024];
WideCharToMultiByte(CP_ACP, 0, buffer, -1, bufferA, 1024, NULL, NULL);
#endif
SetFilePointer(hFile, 0, 0, FILE_END);
#ifdef UNICODE
WriteFile(hFile, bufferA, lstrlenA(bufferA), &cbWritten, NULL);
#else
WriteFile(hFile, buffer, lstrlen(buffer), &cbWritten, NULL);
#endif
CloseHandle(hFile);
}
#ifdef DEBUG
OutputDebugString(buffer);
#endif
}
void MakeFileName(TCHAR *FileName, TCHAR *Directory, TCHAR *BaseName)
{
TCHAR c = _T('\0');
// copy directory name
while(*Directory)
{
c = *(Directory++);
*(FileName++) = c;
}
// make sure there is "\" or "/" between directory and file name
if(c != _T('\\') && c != _T('/'))
{
*(FileName++) = _T('\\');
}
// append base name
while(*BaseName)
{
*(FileName++) = *(BaseName++);
}
// zero-terminate resulting file name
*(FileName++) = _T('\0');
}
BOOL MyDeleteService(TCHAR *ServiceName)
{
BOOL success = FALSE;
SC_HANDLE hSvcMgr = NULL;
SC_HANDLE hService = NULL;
SERVICE_STATUS ServiceStatus;
DWORD checkPoint;
CHECK(hSvcMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS));
hService = OpenService(hSvcMgr, ServiceName, SERVICE_ALL_ACCESS);
if(hService == NULL)
{
if(GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
{
success = TRUE;
goto Cleanup;
}
TRACE((_T("Failed to open service\n")));
}
if(ControlService(hService, SERVICE_CONTROL_STOP, &ServiceStatus))
{
while(ServiceStatus.dwCurrentState != SERVICE_STOPPED)
{
checkPoint = ServiceStatus.dwCheckPoint;
Sleep(ServiceStatus.dwWaitHint);
CHECK(QueryServiceStatus(hService, &ServiceStatus));
CHECK(ServiceStatus.dwCheckPoint != checkPoint);
}
}
else
{
CHECK(GetLastError() == ERROR_SERVICE_NOT_ACTIVE);
}
CHECK(DeleteService(hService));
success = TRUE;
Cleanup:
if(hService) CloseServiceHandle(hService);
if(hSvcMgr) CloseServiceHandle(hSvcMgr);
return success;
}
BOOL
MyDeleteFile(TCHAR *File)
{
BOOL success = FALSE;
TCHAR Backup[MAX_PATH];
DWORD dwAttributes;
dwAttributes = GetFileAttributes(File);
if(dwAttributes == -1 || DeleteFile(File))
{
success = TRUE;
goto Cleanup;
}
lstrcpy(Backup, File);
lstrcat(Backup, _T(".deleted"));
dwAttributes = GetFileAttributes(Backup);
if(dwAttributes != -1)
{
if(!DeleteFile(Backup))
{
TRACE((_T("Can't delete %s, GetLastError() = \n"), Backup, GetLastError()));
goto Cleanup;
}
}
success = MoveFile(File, Backup);
MoveFileEx(Backup, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
Cleanup:
return success;
}
BOOL
MyMoveFile(
TCHAR *File,
TCHAR *SourceDir,
TCHAR *DestinationDir)
/*++
--*/
{
BOOL success = FALSE;
TCHAR Source[MAX_PATH];
TCHAR Destination[MAX_PATH];
DWORD dwAttributes;
MakeFileName(Source, SourceDir, File);
if(DestinationDir != NULL)
{
//
// If backup directory is specified, produce destination file name
//
MakeFileName(Destination, DestinationDir, File);
//
// Delete the destination file if it exists
//
dwAttributes = GetFileAttributes(Destination);
if(dwAttributes == -1)
{
//
// We don't expect this to fail even if file is in use
//
CHECK2(MoveFile(Source, Destination), ("%s %s", Source, Destination));
}
else
{
// Destination file already exists -- don't clobber it,
// just delete the source file
CHECK2(MyDeleteFile(Source), ("%s", Source));
}
}
else
{
//
// If backup directory is not specified, we just delete the source file
//
CHECK2(MyDeleteFile(Source), ("%s", Source));
}
success = TRUE;
Cleanup:
return success;
}
BOOL
MyDeleteDirectory(
TCHAR *Directory)
{
BOOL success = TRUE;
TCHAR path[MAX_PATH];
WIN32_FIND_DATA fd;
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwAttributes;
dwAttributes = GetFileAttributes(Directory);
if(dwAttributes == -1) {
success = TRUE;
goto Cleanup;
}
CHECK((dwAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
MakeFileName(path, Directory, _T("*.*"));
hFind = FindFirstFile(path, &fd);
while(hFind != INVALID_HANDLE_VALUE)
{
// delete any file or directory that is not "." or ".."
if(lstrcmp(fd.cFileName, _T(".")) != 0 &&
lstrcmp(fd.cFileName, _T("..")) != 0)
{
MakeFileName(path, Directory, fd.cFileName);
dwAttributes = GetFileAttributes(path);
if(dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
CHECK2(MyDeleteDirectory(path), ("%s", path));
} else {
CHECK2(MyDeleteFile(path), ("%s", path));
}
}
// if no more files,
// close enumerator (and thus break out of loop)
if(!FindNextFile(hFind, &fd))
{
FindClose(hFind);
hFind = INVALID_HANDLE_VALUE;
}
}
// don't forget to delete the directory
CHECK2(RemoveDirectory(Directory), ("%s", Directory));
success = TRUE;
Cleanup:
// if we jumped out of while() loop in error,
// don't leave enumerator orphaned
if(hFind != INVALID_HANDLE_VALUE)
{
FindClose(hFind);
}
return success;
}
BOOL MyRegDeleteKey(HKEY hKey, TCHAR *subkey)
{
BOOL success;
UINT result;
result = RegDeleteKey(hKey, subkey);
success = (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
if(!success)
{
SetLastError(result);
}
return success;
}
BOOL RegisterServer32(TCHAR *Module, TCHAR *Options)
{
BOOL success = FALSE;
STARTUPINFO si;
PROCESS_INFORMATION pi;
TCHAR Regsvr32[MAX_PATH];
TCHAR *CmdLine = NULL;
CHECK(ExpandEnvironmentStrings(_T("%SystemRoot%\\system32\\regsvr32.exe "), Regsvr32, MAX_PATH));
CmdLine = (TCHAR *)LocalAlloc(LPTR,
sizeof(TCHAR) * (2 + lstrlen(Options) + lstrlen(Module) + lstrlen(Regsvr32)));
CHECK(CmdLine != NULL);
lstrcpy(CmdLine, Regsvr32);
lstrcat(CmdLine, Options);
lstrcat(CmdLine, _T(" "));
lstrcat(CmdLine, Module);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
CHECK2(CreateProcess(NULL, CmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi), ("%s", CmdLine));
CHECK(WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_OBJECT_0);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
success = TRUE;
Cleanup:
if(CmdLine) LocalFree((HLOCAL) CmdLine);
return success;
}
BOOL IsFirstFileOlderThanSecond(TCHAR *FirstFile, TCHAR *SecondFile)
{
BOOL success = FALSE;
DWORD dwFirst, dwSecond;
LPVOID pFirst = NULL;
LPVOID pSecond = NULL;
DWORD dummy;
VS_FIXEDFILEINFO *pvFirst;
VS_FIXEDFILEINFO *pvSecond;
UINT uFirst, uSecond;
dwFirst = GetFileVersionInfoSize(FirstFile, &dummy);
dwSecond = GetFileVersionInfoSize(SecondFile, &dummy);
if(dwFirst == 0 || dwSecond == 0)
{
// one of them does not have version information.
// consider this "not older"
goto Cleanup;
}
CHECK(pFirst = LocalAlloc(LPTR, dwFirst));
CHECK(pSecond = LocalAlloc(LPTR, dwSecond));
CHECK(GetFileVersionInfo(FirstFile, 0, dwFirst, pFirst));
CHECK(GetFileVersionInfo(SecondFile, 0, dwSecond, pSecond));
CHECK(VerQueryValue(pFirst, _T("\\"), &pvFirst, &uFirst) && pvFirst);
CHECK(VerQueryValue(pSecond, _T("\\"), &pvSecond, &uSecond) && pvSecond);
if(pvFirst->dwFileVersionMS > pvSecond->dwFileVersionMS)
{
// first file version is definitely newer
goto Cleanup;
}
if(pvFirst->dwFileVersionMS < pvSecond->dwFileVersionMS)
{
// first file is definitely older
success = TRUE;
}
//
// at this point we know that MS versions are the same
//
success = pvFirst->dwFileVersionLS < pvFirst->dwFileVersionLS;
Cleanup:
if(pFirst) LocalFree(pFirst);
if(pSecond) LocalFree(pSecond);
return success;
}