|
|
#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;
}
|