mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:03:02 +01:00
Win32 HEAD porting of 1.5 branch RC8 latest updates, to keep HEAD in synch with about to be released 1.5.
Please someone check and adjust MSVC7 compile, cause I only have MSVC6.
This commit is contained in:
parent
26af0411a9
commit
a75b48c6a8
@ -36,7 +36,7 @@ if "%ERRLEV%"=="1" goto :END
|
||||
:RELEASE
|
||||
@echo Building release
|
||||
if "%VS_VER%"=="msvc6" (
|
||||
@msdev %ROOT_PATH%\builds\win32\%VS_VER%\Firebird2.dsw /MAKE "fbserver - Win32 Release" "fbguard - Win32 Release" "fb_lock_print - Win32 Release" "fb_inet_server - Win32 Release" "walw - Win32 Release" "archive - Win32 Release" "journal - Win32 Release" "gbak - Win32 Release" "nbackup - Win32 Release" "gpre - Win32 Release" "gsplit - Win32 Release" "gdef - Win32 Release" "gfix - Win32 Release" "gsec - Win32 Release" "gstat - Win32 Release" "instreg - Win32 Release" "instsvc - Win32 Release" "isql - Win32 Release" "qli - Win32 Release" "gds32 - Win32 Release" "fbclient - Win32 Release" "fbudf - Win32 Release" "ib_udf - Win32 Release" "ib_util - Win32 Release" "intl - Win32 Release" %CLEAN% /OUT all.log
|
||||
@msdev %ROOT_PATH%\builds\win32\%VS_VER%\Firebird2.dsw /MAKE "fbserver - Win32 Release" "fbguard - Win32 Release" "fb_lock_print - Win32 Release" "fb_inet_server - Win32 Release" "walw - Win32 Release" "archive - Win32 Release" "journal - Win32 Release" "gbak - Win32 Release" "nbackup - Win32 Release" "gpre - Win32 Release" "gsplit - Win32 Release" "gdef - Win32 Release" "gfix - Win32 Release" "gsec - Win32 Release" "gstat - Win32 Release" "instreg - Win32 Release" "instsvc - Win32 Release" "instclient - Win32 Release" "isql - Win32 Release" "qli - Win32 Release" "fbclient - Win32 Release" "fbudf - Win32 Release" "ib_udf - Win32 Release" "ib_util - Win32 Release" "intl - Win32 Release" %CLEAN% /OUT all.log
|
||||
) else (
|
||||
@devenv %ROOT_PATH%\builds\win32\%VS_VER%\Firebird2.sln %CLEAN% release /OUT all.log
|
||||
)
|
||||
@ -54,7 +54,7 @@ goto :EOF
|
||||
:DEBUG
|
||||
@echo Building debug
|
||||
if "%VS_VER%"=="msvc6" (
|
||||
@msdev %ROOT_PATH%\builds\win32\%VS_VER%\Firebird2.dsw /MAKE "fbserver - Win32 Debug" "fbguard - Win32 Debug" "fb_lock_print - Win32 Debug" "fb_inet_server - Win32 Debug" "walw - Win32 Debug" "archive - Win32 Debug" "journal - Win32 Debug" "gbak - Win32 Debug" "nbackup - Win32 Debug" "gpre - Win32 Debug" "gsplit - Win32 Debug" "gdef - Win32 Debug" "gfix - Win32 Debug" "gsec - Win32 Debug" "gstat - Win32 Debug" "instreg - Win32 Debug" "instsvc - Win32 Debug" "isql - Win32 Debug" "qli - Win32 Debug" "gds32 - Win32 Debug" "fbclient - Win32 Debug" "fbudf - Win32 Debug" "ib_udf - Win32 Debug" "ib_util - Win32 Debug" "intl - Win32 Debug" %CLEAN% /OUT all.log
|
||||
@msdev %ROOT_PATH%\builds\win32\%VS_VER%\Firebird2.dsw /MAKE "fbserver - Win32 Debug" "fbguard - Win32 Debug" "fb_lock_print - Win32 Debug" "fb_inet_server - Win32 Debug" "walw - Win32 Debug" "archive - Win32 Debug" "journal - Win32 Debug" "gbak - Win32 Debug" "nbackup - Win32 Debug" "gpre - Win32 Debug" "gsplit - Win32 Debug" "gdef - Win32 Debug" "gfix - Win32 Debug" "gsec - Win32 Debug" "gstat - Win32 Debug" "instreg - Win32 Debug" "instsvc - Win32 Debug" "instclient - Win32 Release" "isql - Win32 Debug" "qli - Win32 Debug" "fbclient - Win32 Debug" "fbudf - Win32 Debug" "ib_udf - Win32 Debug" "ib_util - Win32 Debug" "intl - Win32 Debug" %CLEAN% /OUT all.log
|
||||
) else (
|
||||
@devenv %ROOT_PATH%\builds\win32\%VS_VER%\Firebird2.sln %CLEAN% debug /OUT all.log
|
||||
)
|
||||
@ -95,7 +95,6 @@ goto :EOF
|
||||
@copy %ROOT_PATH%\gen\firebird.msg %ROOT_PATH%\output\firebird.msg >nul
|
||||
@copy %ROOT_PATH%\builds\misc\security.gbak %ROOT_PATH%\output\security.fbk > nul
|
||||
:: LIB
|
||||
@copy %ROOT_PATH%\temp\%DBG_DIR%\gds32\gds32.lib %ROOT_PATH%\output\lib\gds32_ms.lib >nul
|
||||
@copy %ROOT_PATH%\temp\%DBG_DIR%\fbclient\fbclient.lib %ROOT_PATH%\output\lib\fbclient_ms.lib >nul
|
||||
:: DOCS
|
||||
@copy %ROOT_PATH%\ChangeLog %ROOT_PATH%\output\doc\ChangeLog.txt >nul
|
||||
|
@ -510,6 +510,18 @@ Package=<4>
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "instclient"=.\instclient.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "instreg"=.\instreg.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
|
116
builds/win32/msvc6/instclient.dsp
Normal file
116
builds/win32/msvc6/instclient.dsp
Normal file
@ -0,0 +1,116 @@
|
||||
# Microsoft Developer Studio Project File - Name="instclient" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=instclient - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "instclient.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "instclient.mak" CFG="instclient - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "instclient - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "instclient - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "instclient - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ""
|
||||
# PROP BASE Intermediate_Dir ""
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "..\..\..\temp\debug\instclient"
|
||||
# PROP Intermediate_Dir "..\..\..\temp\debug\instclient"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../../../src/include" /I "../../../src/include/gen" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "SUPERCLIENT" /D "DEV_BUILD" /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x41d /d "_DEBUG"
|
||||
# ADD RSC /l 0x41d /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib shell32.lib comctl32.lib advapi32.lib ws2_32.lib mpr.lib version.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"..\..\..\temp\debug\firebird/bin/instclient.exe" /pdbtype:sept
|
||||
|
||||
!ELSEIF "$(CFG)" == "instclient - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ""
|
||||
# PROP BASE Intermediate_Dir ""
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "..\..\..\temp\release\instclient"
|
||||
# PROP Intermediate_Dir "..\..\..\temp\release\instclient"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "../../../src/include" /I "../../../src/include/gen" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
|
||||
# SUBTRACT BASE CPP /YX
|
||||
# ADD CPP /nologo /MD /W3 /GX /Zi /Ot /Og /Oi /Op /Oy /Ob1 /I "../../../src/include" /I "../../../src/include/gen" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "SUPERCLIENT" /FD /EHc- /c
|
||||
# ADD BASE RSC /l 0x41d /d "_DEBUG"
|
||||
# ADD RSC /l 0x41d /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib shell32.lib comctl32.lib advapi32.lib ws2_32.lib mpr.lib version.lib /nologo /subsystem:console /incremental:no /machine:I386 /out:"..\..\..\temp\release\firebird/bin/instclient.exe" /pdbtype:sept
|
||||
# SUBTRACT LINK32 /debug
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "instclient - Win32 Debug"
|
||||
# Name "instclient - Win32 Release"
|
||||
# Begin Group "UTILITIES files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\utilities\install\install.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\utilities\install\install_client.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\utilities\install_proto.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource files"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\src\jrd\version.rc
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
164
builds/win32/msvc7/instclient.vcproj
Normal file
164
builds/win32/msvc7/instclient.vcproj
Normal file
@ -0,0 +1,164 @@
|
||||
<?xml version="1.0" encoding = "Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.00"
|
||||
Name="instclient"
|
||||
SccProjectName=""
|
||||
SccLocalPath="">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="..\..\..\temp\release\instclient"
|
||||
IntermediateDirectory="..\..\..\temp\release\instclient"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/EHc- "
|
||||
Optimization="4"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="1"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
ImproveFloatingPointConsistency="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"
|
||||
AdditionalIncludeDirectories="../../../src/include,../../../src/include/gen"
|
||||
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE,SUPERCLIENT"
|
||||
RuntimeLibrary="2"
|
||||
PrecompiledHeaderFile="..\..\..\temp\release\instclient/instclient.pch"
|
||||
AssemblerListingLocation="..\..\..\temp\release\instclient/"
|
||||
ObjectFile="..\..\..\temp\release\instclient/"
|
||||
ProgramDataBaseFileName="..\..\..\temp\release\instclient/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib"
|
||||
OutputFile="release/firebird/bin/instclient.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
ProgramDatabaseFile="..\..\..\temp\release\instclient/instclient.pdb"
|
||||
SubSystem="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName="..\..\..\temp\release\instclient/instclient.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1053"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="..\..\..\temp\debug\instclient"
|
||||
IntermediateDirectory="..\..\..\temp\debug\instclient"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../../src/include,../../../src/include/gen"
|
||||
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE,SUPERCLIENT,DEV_BUILD"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
PrecompiledHeaderFile="..\..\..\temp\debug\instclient/instclient.pch"
|
||||
AssemblerListingLocation="..\..\..\temp\debug\instclient/"
|
||||
ObjectFile="..\..\..\temp\debug\instclient/"
|
||||
ProgramDataBaseFileName="..\..\..\temp\debug\instclient/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
AdditionalDependencies="comctl32.lib ws2_32.lib mpr.lib version.lib"
|
||||
OutputFile="debug/firebird/bin/instclient.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="..\..\..\temp\debug\instclient/instclient.pdb"
|
||||
SubSystem="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName="..\..\..\temp\debug\instclient/instclient.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1053"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="UTILITIES files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||
<File
|
||||
RelativePath="..\..\..\src\utilities\install_client.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\utilities\install.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header files"
|
||||
Filter="h;hpp;hxx;hm;inl">
|
||||
<File
|
||||
RelativePath="..\..\..\src\utilities\install_proto.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource files"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\version.rc">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\..\src\jrd;$(NoInherit)"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\..\src\jrd;$(NoInherit)"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
757
src/utilities/install/install.cpp
Normal file
757
src/utilities/install/install.cpp
Normal file
@ -0,0 +1,757 @@
|
||||
/*
|
||||
* PROGRAM: Windows Win32 Client Library Installation Tools
|
||||
* MODULE: install.cpp
|
||||
* DESCRIPTION: Functions which help installing components to WinSysDir
|
||||
*
|
||||
* The contents of this file are subject to the Initial Developer's
|
||||
* Public License Version 1.0 (the "License"); you may not use this
|
||||
* file except in compliance with the License. You may obtain a copy
|
||||
* of the License here:
|
||||
*
|
||||
* http://www.ibphoenix.com?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code is (C) 2003 Olivier Mascia.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Olivier Mascia.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../jrd/ib_stdio.h"
|
||||
#include <windows.h>
|
||||
#include "../jrd/common.h"
|
||||
#include "../jrd/license.h"
|
||||
#include "../utilities/install/install_nt.h"
|
||||
#include "../utilities/install/install_proto.h"
|
||||
|
||||
#define GDSVER_MAJOR 6
|
||||
#define GDSVER_MINOR 3
|
||||
|
||||
#define SHARED_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs"
|
||||
|
||||
namespace {
|
||||
|
||||
USHORT GetVersion(const TEXT* gds32, DWORD& verMS, DWORD& verLS,
|
||||
USHORT(*err_handler)(ULONG, const TEXT *));
|
||||
|
||||
USHORT PatchVersion(const TEXT* gds32, DWORD verMS,
|
||||
USHORT(*err_handler)(ULONG, const TEXT *));
|
||||
|
||||
USHORT IncrementSharedCount(const TEXT* gds32,
|
||||
USHORT(*err_handler)(ULONG, const TEXT *));
|
||||
|
||||
USHORT DecrementSharedCount(const TEXT* gds32, bool sw_force,
|
||||
USHORT(*err_handler)(ULONG, const TEXT *));
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
// --- Public Functions ---
|
||||
//
|
||||
|
||||
USHORT CLIENT_install(const TEXT * rootdir, USHORT client, bool sw_force,
|
||||
USHORT(*err_handler)(ULONG, const TEXT *))
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* C L I E N T _ i n s t a l l
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Depending on the USHORT client parameter, installs FBCLIENT.DLL or
|
||||
* GDS32.DLL in the Windows System directory.
|
||||
*
|
||||
* When installing and -force is NOT used then
|
||||
*
|
||||
* test for existence of client library
|
||||
* if earlier version then copy, increment shared library count
|
||||
* if same version then do nothing
|
||||
* if later version then do nothing
|
||||
*
|
||||
* If -force is supplied then
|
||||
*
|
||||
* test for existence of client library
|
||||
* if the version doesn't match then copy, increment shared library count
|
||||
* else do nothing
|
||||
*
|
||||
**************************************/
|
||||
|
||||
// Get Windows System Directory
|
||||
TEXT sysdir[MAXPATHLEN];
|
||||
int len = GetSystemDirectory(sysdir, sizeof(sysdir));
|
||||
if (len == 0)
|
||||
return (*err_handler) (GetLastError(), "GetSystemDirectory()");
|
||||
|
||||
// Compute newverMS and newverLS. They will contain the full client version
|
||||
// number that we intend to install to WinSysDir.
|
||||
TEXT fbdll[MAXPATHLEN];
|
||||
lstrcpy(fbdll, rootdir);
|
||||
lstrcat(fbdll, "\\bin\\");
|
||||
lstrcat(fbdll, FBCLIENT_NAME);
|
||||
|
||||
DWORD newverMS = 0, newverLS = 0;
|
||||
USHORT status = GetVersion(fbdll, newverMS, newverLS, err_handler);
|
||||
if (status != FB_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (client == CLIENT_GDS)
|
||||
{
|
||||
// For the GDS32.DLL installation, the major/minor version is hardcoded
|
||||
newverMS = (GDSVER_MAJOR << 16) | GDSVER_MINOR;
|
||||
}
|
||||
|
||||
// Check for existence and version of current installed DLL
|
||||
TEXT target[MAXPATHLEN];
|
||||
lstrcpy(target, sysdir);
|
||||
lstrcat(target, "\\");
|
||||
lstrcat(target, client == CLIENT_GDS ? GDS32_NAME : FBCLIENT_NAME);
|
||||
|
||||
DWORD targetverMS = 0, targetverLS = 0;
|
||||
status = GetVersion(target, targetverMS, targetverLS, err_handler);
|
||||
if (status == FB_FAILURE)
|
||||
return FB_FAILURE;
|
||||
|
||||
if (status == FB_SUCCESS)
|
||||
{
|
||||
// The target DLL already exists
|
||||
if (! sw_force)
|
||||
{
|
||||
if (targetverMS > targetverMS)
|
||||
return FB_INSTALL_NEWER_VERSION_FOUND;
|
||||
if (targetverMS == newverMS && targetverLS > newverLS)
|
||||
return FB_INSTALL_NEWER_VERSION_FOUND;
|
||||
}
|
||||
if (targetverMS == newverMS && targetverLS == newverLS)
|
||||
return FB_INSTALL_SAME_VERSION_FOUND;
|
||||
}
|
||||
|
||||
// Copy FBCLIENT.DLL as _FBCLIENT.DLL (in WinSysDir).
|
||||
// Such a step is needed because the MoveFile techniques used later
|
||||
// can't span different volumes. So the intermediate target has to be
|
||||
// already on the same final destination volume as the final target.
|
||||
TEXT workfile[MAXPATHLEN];
|
||||
lstrcpy(workfile, sysdir);
|
||||
lstrcat(workfile, "\\_");
|
||||
lstrcat(workfile, FBCLIENT_NAME);
|
||||
|
||||
if (CopyFile(fbdll, workfile, FALSE) == 0)
|
||||
{
|
||||
return (*err_handler) (GetLastError(),
|
||||
"CopyFile(FBCLIENT.DLL, WinSysDir\\_FBCLIENT.DLL)");
|
||||
}
|
||||
|
||||
if (client == CLIENT_GDS)
|
||||
{
|
||||
// Patch File Version, this is needed only for GDS32.DLL.
|
||||
status = PatchVersion(workfile, newverMS, err_handler);
|
||||
if (status != FB_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
||||
// Move _FBCLIENT.DLL as the final target
|
||||
if (MoveFile(workfile, target) == 0)
|
||||
{
|
||||
// MoveFile failed, this is expected if target already exists
|
||||
ULONG werr = GetLastError();
|
||||
if (werr != ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
DeleteFile(workfile);
|
||||
return (*err_handler) (werr,
|
||||
"MoveFile(_FBCLIENT.DLL, 'target')");
|
||||
}
|
||||
|
||||
// Failed moving because a destination target file already exists
|
||||
// Let's try again by attempting a remove of the destination
|
||||
if (DeleteFile(target) != 0)
|
||||
{
|
||||
// Success deleting the target, MoveFile should now succeed.
|
||||
if (MoveFile(workfile, target) != 0)
|
||||
{
|
||||
// Successfull !
|
||||
IncrementSharedCount(target, err_handler);
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// Deleting the target failed OR moving after target delete failed.
|
||||
// Let's try once more using reboot-time update.
|
||||
HMODULE kernel32 = LoadLibrary("KERNEL32.DLL");
|
||||
if (kernel32 != 0)
|
||||
{
|
||||
typedef BOOL __stdcall proto_ntmove(LPCSTR, LPCSTR, DWORD);
|
||||
proto_ntmove* ntmove =
|
||||
(proto_ntmove*)GetProcAddress(kernel32, "MoveFileExA");
|
||||
if (ntmove != 0)
|
||||
{
|
||||
// We are definitely running on a system supporting the
|
||||
// MoveFileEx API. Let's use it for setting up the reboot-copy.
|
||||
|
||||
if ((*ntmove) (target, 0, MOVEFILE_DELAY_UNTIL_REBOOT) == 0)
|
||||
{
|
||||
ULONG werr = GetLastError();
|
||||
FreeLibrary(kernel32);
|
||||
DeleteFile(workfile);
|
||||
return (*err_handler) (werr, "MoveFileEx(delete 'target')");
|
||||
}
|
||||
|
||||
if ((*ntmove) (workfile, target, MOVEFILE_DELAY_UNTIL_REBOOT) == 0)
|
||||
{
|
||||
ULONG werr = GetLastError();
|
||||
FreeLibrary(kernel32);
|
||||
DeleteFile(workfile);
|
||||
return (*err_handler) (werr, "MoveFileEx(replace 'target')");
|
||||
}
|
||||
|
||||
FreeLibrary(kernel32);
|
||||
IncrementSharedCount(target, err_handler);
|
||||
return FB_INSTALL_COPY_REQUIRES_REBOOT;
|
||||
}
|
||||
|
||||
FreeLibrary(kernel32);
|
||||
}
|
||||
|
||||
// We are running a system which doesn't support MoveFileEx API.
|
||||
// Let's use the WININIT.INI method (Win95/98/Me).
|
||||
// For this we need "short file names".
|
||||
|
||||
TEXT ssysdir[MAXPATHLEN];
|
||||
if (GetShortPathName(sysdir, ssysdir, sizeof(ssysdir)) == 0)
|
||||
return (*err_handler) (GetLastError(), "GetShortPathName()");
|
||||
|
||||
TEXT sworkfile[MAXPATHLEN];
|
||||
lstrcpy(sworkfile, ssysdir);
|
||||
lstrcat(sworkfile, "\\_");
|
||||
lstrcat(sworkfile, FBCLIENT_NAME);
|
||||
|
||||
TEXT starget[MAXPATHLEN];
|
||||
lstrcpy(starget, ssysdir);
|
||||
lstrcat(starget, "\\");
|
||||
lstrcat(starget, client == CLIENT_GDS ? GDS32_NAME : FBCLIENT_NAME);
|
||||
|
||||
if (WritePrivateProfileString("rename", "NUL", starget,
|
||||
"WININIT.INI") == 0)
|
||||
{
|
||||
ULONG werr = GetLastError();
|
||||
DeleteFile(workfile);
|
||||
return (*err_handler) (werr,
|
||||
"WritePrivateProfileString(delete 'target')");
|
||||
}
|
||||
|
||||
if (WritePrivateProfileString("rename", starget, sworkfile,
|
||||
"WININIT.INI") == 0)
|
||||
{
|
||||
ULONG werr = GetLastError();
|
||||
DeleteFile(workfile);
|
||||
return (*err_handler) (werr,
|
||||
"WritePrivateProfileString(replace 'target')");
|
||||
}
|
||||
|
||||
IncrementSharedCount(target, err_handler);
|
||||
return FB_INSTALL_COPY_REQUIRES_REBOOT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Straight plain MoveFile succeeded immediately.
|
||||
IncrementSharedCount(target, err_handler);
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
USHORT CLIENT_remove(const TEXT * rootdir, USHORT client, bool sw_force,
|
||||
USHORT(*err_handler)(ULONG, const TEXT *))
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* C L I E N T _ r e m o v e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Depending on the USHORT client parameter, remove FBCLIENT.DLL or GDS32.DLL
|
||||
* from the Windows System directory.
|
||||
*
|
||||
* when removing and -force is NOT used
|
||||
*
|
||||
* test for existence of client library
|
||||
* if version matches then decrement shared library count
|
||||
* if count=0 then delete library, remove entry from shared library
|
||||
* if version doesn't match then do nothing. It is not ours.
|
||||
*
|
||||
* when removing and -force IS used
|
||||
*
|
||||
* test for existence of client library
|
||||
* if version matches then delete library, remove entry for shared library
|
||||
* if version doesn't match then do nothing. It is not ours.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
// Get Windows System Directory
|
||||
TEXT sysdir[MAXPATHLEN];
|
||||
int len = GetSystemDirectory(sysdir, sizeof(sysdir));
|
||||
if (len == 0)
|
||||
return (*err_handler) (GetLastError(), "GetSystemDirectory()");
|
||||
|
||||
// Compute ourverMS and ourverLS. They will contain the full client version
|
||||
// number that we could have installed to WinSysDir.
|
||||
TEXT fbdll[MAXPATHLEN];
|
||||
lstrcpy(fbdll, rootdir);
|
||||
lstrcat(fbdll, "\\bin\\");
|
||||
lstrcat(fbdll, FBCLIENT_NAME);
|
||||
|
||||
DWORD ourverMS = 0, ourverLS = 0;
|
||||
USHORT status = GetVersion(fbdll, ourverMS, ourverLS, err_handler);
|
||||
if (status != FB_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (client == CLIENT_GDS)
|
||||
{
|
||||
// For the GDS32.DLL, the major/minor version is hardcoded
|
||||
ourverMS = (GDSVER_MAJOR << 16) | GDSVER_MINOR;
|
||||
}
|
||||
|
||||
// Check for existence and version of current installed client
|
||||
TEXT target[MAXPATHLEN];
|
||||
lstrcpy(target, sysdir);
|
||||
lstrcat(target, "\\");
|
||||
lstrcat(target, client == CLIENT_GDS ? GDS32_NAME : FBCLIENT_NAME);
|
||||
|
||||
DWORD targetverMS = 0, targetverLS = 0;
|
||||
status = GetVersion(target, targetverMS, targetverLS, err_handler);
|
||||
if (status != FB_SUCCESS)
|
||||
return status; // FB_FAILURE or FB_INSTALL_FILE_NOT_FOUND
|
||||
|
||||
if (targetverMS != ourverMS || targetverLS != ourverLS)
|
||||
return FB_INSTALL_CANT_REMOVE_ALIEN_VERSION;
|
||||
|
||||
status = DecrementSharedCount(target, sw_force, err_handler);
|
||||
if (status == FB_INSTALL_SHARED_COUNT_ZERO)
|
||||
{
|
||||
if (! DeleteFile(target))
|
||||
{
|
||||
// Could not delete the file, restore shared count
|
||||
IncrementSharedCount(target, err_handler);
|
||||
return FB_INSTALL_FILE_PROBABLY_IN_USE;
|
||||
}
|
||||
}
|
||||
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
USHORT CLIENT_query(USHORT client, ULONG& verMS, ULONG& verLS,
|
||||
ULONG& sharedCount, USHORT(*err_handler)(ULONG, const TEXT *))
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* C L I E N T _ q u e r y
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Depending on the USHORT client parameter, returns version info and
|
||||
* shared dll count of the currently installed GDS32.DLL or FBCLIENT.DLL.
|
||||
* Eventually return FB_INSTALL_FILE_NOT_FOUND.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
// Get Windows System Directory
|
||||
TEXT sysdir[MAXPATHLEN];
|
||||
int len = GetSystemDirectory(sysdir, sizeof(sysdir));
|
||||
if (len == 0)
|
||||
return (*err_handler) (GetLastError(), "GetSystemDirectory()");
|
||||
|
||||
TEXT target[MAXPATHLEN];
|
||||
lstrcpy(target, sysdir);
|
||||
lstrcat(target, "\\");
|
||||
lstrcat(target, client == CLIENT_GDS ? GDS32_NAME : FBCLIENT_NAME);
|
||||
|
||||
verMS = verLS = sharedCount = 0;
|
||||
USHORT status = GetVersion(target, verMS, verLS, err_handler);
|
||||
if (status != FB_SUCCESS)
|
||||
return status; // FB_FAILURE or FB_INSTALL_FILE_NOT_FOUND
|
||||
|
||||
HKEY hkey;
|
||||
LONG keystatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SHARED_KEY, 0,
|
||||
KEY_READ, &hkey);
|
||||
if (keystatus != ERROR_SUCCESS)
|
||||
return (*err_handler) (keystatus, "RegOpenKeyEx");
|
||||
|
||||
DWORD type, size = sizeof(sharedCount);
|
||||
sharedCount = 0;
|
||||
keystatus = RegQueryValueEx(hkey, target, NULL, &type,
|
||||
reinterpret_cast<BYTE*>(&sharedCount), &size);
|
||||
if (keystatus != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hkey);
|
||||
return (*err_handler) (keystatus, "RegQueryValueEx");
|
||||
}
|
||||
RegCloseKey(hkey);
|
||||
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// --- Local Functions ---
|
||||
//
|
||||
|
||||
namespace {
|
||||
|
||||
USHORT GetVersion(const TEXT* filename, DWORD& verMS, DWORD& verLS,
|
||||
USHORT(*err_handler)(ULONG, const TEXT *))
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* G e t V e r s i o n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Get the file version of a dll whose full path and name is given.
|
||||
* Returns a status value to report a failure, a non-existing file or success.
|
||||
* 'version' is only updated in case of success.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
HANDLE hfile = CreateFile(filename, GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
if (hfile == INVALID_HANDLE_VALUE)
|
||||
return FB_INSTALL_FILE_NOT_FOUND;
|
||||
|
||||
// We'll keep hfile opened until we have read version so that the file
|
||||
// can't be deleted between check for existence and version read.
|
||||
|
||||
DWORD dwUnused;
|
||||
DWORD rsize = GetFileVersionInfoSize(const_cast<TEXT*>(filename), &dwUnused);
|
||||
if (rsize == 0)
|
||||
{
|
||||
ULONG werr = GetLastError();
|
||||
CloseHandle(hfile);
|
||||
return (*err_handler) (werr, "GetFileVersionInfoSize()");
|
||||
}
|
||||
|
||||
BYTE* hver = new BYTE[rsize];
|
||||
if (! GetFileVersionInfo(const_cast<TEXT*>(filename), 0, rsize, hver))
|
||||
{
|
||||
ULONG werr = GetLastError();
|
||||
delete [] hver;
|
||||
CloseHandle(hfile);
|
||||
return (*err_handler) (werr, "GetFileVersionInfo()");
|
||||
}
|
||||
CloseHandle(hfile); // Not needed anymore
|
||||
|
||||
VS_FIXEDFILEINFO* ffi;
|
||||
UINT uiUnused;
|
||||
if (! VerQueryValue(hver, "\\", (void**)&ffi, &uiUnused))
|
||||
{
|
||||
ULONG werr = GetLastError();
|
||||
delete [] hver;
|
||||
return (*err_handler) (werr, "VerQueryValue()");
|
||||
}
|
||||
|
||||
verMS = ffi->dwFileVersionMS;
|
||||
verLS = ffi->dwFileVersionLS;
|
||||
|
||||
delete [] hver;
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
USHORT PatchVersion(const TEXT* filename, DWORD verMS,
|
||||
USHORT(*err_handler)(ULONG, const TEXT *))
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* P a t c h V e r s i o n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Patches the FileVersion and ProductVersion of a DLL whose full
|
||||
* path is given as "filename" parameter. The function only updates the major
|
||||
* and minor version numbers, leaving the sub-minor and build intact.
|
||||
* We typically use this trick to build a GDS32.DLL whose version is 6.3
|
||||
* from our FBCLIENT.DLL whose version is 1.5.
|
||||
*
|
||||
* The politically correct way (speaking of Win32 API) of changing the
|
||||
* version info, should involve using GetFileVersionInfo() and VerQueryValue()
|
||||
* to read the existing version resource, and using BeginUpdateResource(),
|
||||
* UpdateResource() and EndUpdateResource() to actually update the dll file.
|
||||
* Unfortunately those last 3 APIs are not implemented on Win95/98/Me.
|
||||
*
|
||||
* Therefore this function proceeds by straight hacking of the dll file.
|
||||
* This is not intellectually satisfactory, but does work perfectly and
|
||||
* fits the bill.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
HANDLE hfile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
|
||||
0 /* FILE_SHARE_NONE */, 0, OPEN_EXISTING,
|
||||
FILE_FLAG_SEQUENTIAL_SCAN, 0);
|
||||
if (hfile == INVALID_HANDLE_VALUE)
|
||||
return (*err_handler) (GetLastError(), "CreateFile()");
|
||||
|
||||
DWORD fsize = GetFileSize(hfile, 0);
|
||||
|
||||
HANDLE hmap = CreateFileMapping(hfile, 0,
|
||||
PAGE_READWRITE | SEC_COMMIT, 0, 0, 0);
|
||||
if (hmap == 0)
|
||||
{
|
||||
ULONG werr = GetLastError();
|
||||
CloseHandle(hfile);
|
||||
return (*err_handler) (werr, "CreateFileMapping()");
|
||||
}
|
||||
|
||||
BYTE* mem = static_cast<BYTE*>(MapViewOfFile(hmap,
|
||||
FILE_MAP_WRITE, 0, 0, 0));
|
||||
if (mem == 0)
|
||||
{
|
||||
ULONG werr = GetLastError();
|
||||
CloseHandle(hmap);
|
||||
CloseHandle(hfile);
|
||||
return (*err_handler) (werr, "MapViewOfFile()");
|
||||
}
|
||||
|
||||
// This is a "magic value" that will allow locating the version info.
|
||||
// Windows itself does something equivalent internally.
|
||||
BYTE lookup[] = {'V', 0, 'S', 0, '_', 0,
|
||||
'V', 0, 'E', 0, 'R', 0, 'S', 0, 'I', 0, 'O', 0, 'N', 0, '_', 0,
|
||||
'I', 0, 'N', 0, 'F', 0, 'O', 0, 0, 0, 0, 0, 0xbd, 0x04, 0xef, 0xfe};
|
||||
BYTE* p = mem; // First byte of mapped file
|
||||
BYTE* end = mem + fsize; // Last byte + 1 of mapped file
|
||||
|
||||
int i = 0;
|
||||
while (p < end)
|
||||
{
|
||||
if (*p++ == lookup[i])
|
||||
{
|
||||
if (++i == sizeof(lookup)) break;
|
||||
}
|
||||
else i = 0;
|
||||
}
|
||||
|
||||
if (p >= end)
|
||||
{
|
||||
UnmapViewOfFile(mem);
|
||||
CloseHandle(hmap);
|
||||
CloseHandle(hfile);
|
||||
return (*err_handler) (0, "Could not locate the version info resource.");
|
||||
}
|
||||
|
||||
// The VS_FIXEDFILEINFO structure itself is located 4 bytes before the end
|
||||
// of the above "lookup" value (said differently : the first 4 bytes of
|
||||
// FIXEDFILEINFO are the last 4 bytes of the "lookup" value).
|
||||
VS_FIXEDFILEINFO* ffi = (VS_FIXEDFILEINFO*)(p - 4);
|
||||
ffi->dwFileVersionMS = verMS;
|
||||
ffi->dwProductVersionMS = verMS;
|
||||
|
||||
/*
|
||||
ib_printf("Signature: %8.8x\n", ffi->dwSignature);
|
||||
ib_printf("FileVersionMS : %8.8x\n", ffi->dwFileVersionMS);
|
||||
ib_printf("FileVersionLS : %8.8x\n", ffi->dwFileVersionLS);
|
||||
ib_printf("ProductVersionMS : %8.8x\n", ffi->dwProductVersionMS);
|
||||
ib_printf("ProductVersionLS : %8.8x\n", ffi->dwProductVersionLS);
|
||||
*/
|
||||
|
||||
/*
|
||||
// The start of the full VS_VERSIONINFO pseudo structure is located 6 bytes
|
||||
// before the above "lookup" value. This "vi" (versioninfo) pointer points
|
||||
// to the same block of bytes that would have been returned by the
|
||||
// GetFileVersionInfo API.
|
||||
BYTE* vi = p - sizeof(lookup) - 6;
|
||||
|
||||
// The first WORD of this pseudo structure is its byte length
|
||||
WORD viLength = *(WORD*)vi;
|
||||
|
||||
// Let's patch the FileVersion strings (unicode strings).
|
||||
// This patch assumes the original version string has a major version and
|
||||
// a minor version made of a single digit, like 1.5.x.y. It would need
|
||||
// to be updated if we want to use versions like 1.51.x.y.
|
||||
BYTE flookup[] = {'F', 0, 'i', 0, 'l', 0, 'e', 0,
|
||||
'V', 0, 'e', 0, 'r', 0, 's', 0, 'i', 0, 'o', 0, 'n', 0, 0, 0};
|
||||
p = vi;
|
||||
end = vi + viLength;
|
||||
i = 0;
|
||||
while (p < end)
|
||||
{
|
||||
if (*p++ == flookup[i])
|
||||
{
|
||||
if (++i == sizeof(flookup))
|
||||
{
|
||||
// The unicode string is aligned on the next 32 bit value
|
||||
// (See PSDK Version Info "String" pseudo structure.)
|
||||
p = p + ((unsigned int)p % 4);
|
||||
//ib_printf("FileVersion : %ls\n", p);
|
||||
while (! isdigit(*p)) ++p; // Get to first digit
|
||||
*p = (verMS >> 16) + '0'; // Patch major digit
|
||||
while (*p != '.') ++p; // Get to dot
|
||||
while (! isdigit(*p)) ++p; // Get to first digit after dot
|
||||
*p = (verMS & 0xffff) + '0';// Patch minor digit
|
||||
i = 0; // To resume scanning from here (p)
|
||||
}
|
||||
}
|
||||
else i = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// Let's patch the ProductVersion strings.
|
||||
// This patch assumes the original version string has a major version and
|
||||
// a minor version made of a single digit, like 1.5.x.y. It would need
|
||||
// to be updated if we want to use versions like 1.51.x.y.
|
||||
BYTE plookup[] = {'P', 0, 'r', 0, 'o', 0, 'd', 0, 'u', 0, 'c', 0, 't', 0,
|
||||
'V', 0, 'e', 0, 'r', 0, 's', 0, 'i', 0, 'o', 0, 'n', 0, 0, 0};
|
||||
p = vi;
|
||||
end = vi + viLength;
|
||||
i = 0;
|
||||
while (p < end)
|
||||
{
|
||||
if (*p++ == plookup[i])
|
||||
{
|
||||
if (++i == sizeof(plookup))
|
||||
{
|
||||
// The unicode string is aligned on the next 32 bit value
|
||||
// (See PSDK Version Info "String" pseudo structure.)
|
||||
p = p + ((unsigned int)p % 4);
|
||||
//ib_printf("ProductVersion : %ls\n", p);
|
||||
while (! isdigit(*p)) ++p; // Get to first digit
|
||||
*p = (verMS >> 16) + '0'; // Patch major digit
|
||||
while (*p != '.') ++p; // Get to dot
|
||||
while (! isdigit(*p)) ++p; // Get to first digit after dot
|
||||
*p = (verMS & 0xffff) + '0';// Patch minor digit
|
||||
i = 0; // To resume scanning from here (p)
|
||||
}
|
||||
}
|
||||
else i = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
UnmapViewOfFile(mem);
|
||||
CloseHandle(hmap);
|
||||
CloseHandle(hfile);
|
||||
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
USHORT IncrementSharedCount(const TEXT* filename,
|
||||
USHORT(*err_handler)(ULONG, const TEXT *))
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* I n c r e m e n t S h a r e d C o u n t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Increment the registry Shared Count of a module whose full path & file
|
||||
* name is given in parameter 'filename'. Typically used to increment the
|
||||
* shared count of the GDS32.DLL after its installation to WinSysDir. But
|
||||
* can be used for just about any other shared component.
|
||||
* User has to have enough rights to write to the HKLM key tree.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
HKEY hkey;
|
||||
LONG status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, SHARED_KEY,
|
||||
0, "", REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, 0, &hkey, 0);
|
||||
if (status != ERROR_SUCCESS)
|
||||
return (*err_handler) (status, "RegCreateKeyEx");
|
||||
|
||||
DWORD count = 0;
|
||||
DWORD type, size = sizeof(count);
|
||||
RegQueryValueEx(hkey, filename, NULL, &type,
|
||||
reinterpret_cast<BYTE*>(&count), &size);
|
||||
|
||||
++count;
|
||||
|
||||
status = RegSetValueEx(hkey, filename, 0, REG_DWORD,
|
||||
reinterpret_cast<BYTE*>(&count), sizeof(DWORD));
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hkey);
|
||||
return (*err_handler) (status, "RegSetValueEx");
|
||||
}
|
||||
RegCloseKey(hkey);
|
||||
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
USHORT DecrementSharedCount(const TEXT* filename, bool sw_force,
|
||||
USHORT(*err_handler)(ULONG, const TEXT *))
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* D e c r e m e n t S h a r e d C o u n t
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Decrements the registry Shared Count of a module whose full path & file
|
||||
* name is given in parameter 'filename'. Typically used to decrement the
|
||||
* shared count of the GDS32.DLL prior to its eventual removal from WinSysDir.
|
||||
* Can be used for just about any other shared component.
|
||||
* User has to have enough rights to write to the HKLM key tree.
|
||||
* If the shared count reaches zero (or was already zero), the shared count
|
||||
* value is removed and FB_INSTALL_SHARED_COUNT_ZERO is returned.
|
||||
* If the sw_force is set, the shared count value is removed and
|
||||
* FB_INSTALL_SHARED_COUNT_ZERO returned too).
|
||||
* FB_SUCCESS is returned when the count was decremented without reaching
|
||||
* zero. FB_FAILURE is returned only in cases of registry access failures.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
HKEY hkey;
|
||||
DWORD disp;
|
||||
LONG status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, SHARED_KEY,
|
||||
0, "", REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &hkey, &disp);
|
||||
if (status != ERROR_SUCCESS)
|
||||
return (*err_handler) (status, "RegCreateKeyEx");
|
||||
|
||||
LONG count = 0;
|
||||
if (! sw_force)
|
||||
{
|
||||
DWORD type;
|
||||
DWORD size = sizeof(count);
|
||||
RegQueryValueEx(hkey, filename, NULL, &type,
|
||||
reinterpret_cast<BYTE*>(&count), &size);
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
status = RegSetValueEx(hkey, filename, 0, REG_DWORD,
|
||||
reinterpret_cast<BYTE*>(&count), sizeof(DWORD));
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hkey);
|
||||
return (*err_handler) (status, "RegSetValueEx");
|
||||
}
|
||||
RegCloseKey(hkey);
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = RegDeleteValue(hkey, filename);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hkey);
|
||||
return (*err_handler) (status, "RegDeleteValue");
|
||||
}
|
||||
RegCloseKey(hkey);
|
||||
return FB_INSTALL_SHARED_COUNT_ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace { }
|
||||
|
||||
//
|
||||
// EOF
|
||||
//
|
342
src/utilities/install/install_client.cpp
Normal file
342
src/utilities/install/install_client.cpp
Normal file
@ -0,0 +1,342 @@
|
||||
/*
|
||||
* PROGRAM: Windows Win32 Client Libraries Installation
|
||||
* MODULE: install_client.cpp
|
||||
* DESCRIPTION: Program which install the FBCLIENT.DLL or GDS32.DLL
|
||||
*
|
||||
* The contents of this file are subject to the Initial Developer's
|
||||
* Public License Version 1.0 (the "License"); you may not use this
|
||||
* file except in compliance with the License. You may obtain a copy
|
||||
* of the License here:
|
||||
*
|
||||
* http://www.ibphoenix.com?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code is (C) 2003 Olivier Mascia.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Olivier Mascia.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../jrd/ib_stdio.h"
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <conio.h>
|
||||
#include "../jrd/common.h"
|
||||
#include "../jrd/license.h"
|
||||
#include "../utilities/install/install_nt.h"
|
||||
#include "../utilities/install/install_proto.h"
|
||||
|
||||
static USHORT inst_error(ULONG, const TEXT *);
|
||||
static void usage(void);
|
||||
|
||||
static struct
|
||||
{
|
||||
TEXT* name;
|
||||
USHORT abbrev;
|
||||
USHORT code;
|
||||
} commands[] =
|
||||
{
|
||||
{"INSTALL", 1, COMMAND_INSTALL},
|
||||
{"REMOVE", 1, COMMAND_REMOVE},
|
||||
{"QUERY", 1, COMMAND_QUERY},
|
||||
{NULL, 0, 0}
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
TEXT* name;
|
||||
USHORT abbrev;
|
||||
USHORT code;
|
||||
} clients[] =
|
||||
{
|
||||
{"FBCLIENT", 1, CLIENT_FB},
|
||||
{"GDS32", 1, CLIENT_GDS},
|
||||
{NULL, 0, 0}
|
||||
};
|
||||
|
||||
int CLIB_ROUTINE main( int argc, char **argv)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* m a i n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Installs the FBCLIENT.DLL or GDS32.DLL in the Windows system directory.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
USHORT sw_command = COMMAND_NONE;
|
||||
USHORT sw_client = CLIENT_NONE;
|
||||
bool sw_force = false;
|
||||
bool sw_version = false;
|
||||
|
||||
// Let's get the root directory from the instance path of this program.
|
||||
// argv[0] is only _mostly_ guaranteed to give this info,
|
||||
// so we GetModuleFileName()
|
||||
TEXT directory[MAXPATHLEN];
|
||||
USHORT len = GetModuleFileName(NULL, directory, sizeof(directory));
|
||||
if (len == 0)
|
||||
return inst_error(GetLastError(), "GetModuleFileName");
|
||||
|
||||
// Get to the last '\' (this one precedes the filename part). There is
|
||||
// always one after a call to GetModuleFileName().
|
||||
TEXT* p = directory + len;
|
||||
do {--p;} while (*p != '\\');
|
||||
|
||||
// Get to the previous '\' (this one should precede the supposed 'bin\\' part).
|
||||
// There is always an additional '\' OR a ':'.
|
||||
do {--p;} while (*p != '\\' && *p != ':');
|
||||
*p = '\0';
|
||||
|
||||
TEXT** end = argv + argc;
|
||||
while (++argv < end)
|
||||
{
|
||||
if (**argv != '-')
|
||||
{
|
||||
if (sw_command == COMMAND_NONE)
|
||||
{
|
||||
TEXT* cmd;
|
||||
int i;
|
||||
for (i = 0; cmd = commands[i].name; i++)
|
||||
{
|
||||
TEXT* q;
|
||||
for (p = *argv, q = cmd; *p && UPPER(*p) == *q; p++, q++);
|
||||
if (!*p && commands[i].abbrev <= (USHORT) (q - cmd))
|
||||
break;
|
||||
}
|
||||
if (!cmd)
|
||||
{
|
||||
ib_printf("Unknown command \"%s\"\n", *argv);
|
||||
usage();
|
||||
}
|
||||
sw_command = commands[i].code;
|
||||
}
|
||||
else
|
||||
{
|
||||
TEXT* cln;
|
||||
int i;
|
||||
for (i = 0; cln = clients[i].name; i++)
|
||||
{
|
||||
TEXT* q;
|
||||
for (p = *argv, q = cln; *p && UPPER(*p) == *q; p++, q++);
|
||||
if (!*p && clients[i].abbrev <= (USHORT) (q - cln))
|
||||
break;
|
||||
}
|
||||
if (!cln)
|
||||
{
|
||||
ib_printf("Unknown library \"%s\"\n", *argv);
|
||||
usage();
|
||||
}
|
||||
sw_client = clients[i].code;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p = *argv + 1;
|
||||
switch (UPPER(*p))
|
||||
{
|
||||
case 'F':
|
||||
sw_force = true;
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
sw_version = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
ib_printf("Unknown switch \"%s\"\n", p);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sw_version)
|
||||
ib_printf("instclient version %s\n", GDS_VERSION);
|
||||
|
||||
if (sw_command == COMMAND_NONE || sw_client == CLIENT_NONE)
|
||||
{
|
||||
usage();
|
||||
}
|
||||
|
||||
TEXT* clientname = sw_client == CLIENT_GDS ? GDS32_NAME : FBCLIENT_NAME;
|
||||
|
||||
USHORT status;
|
||||
switch (sw_command)
|
||||
{
|
||||
|
||||
case COMMAND_INSTALL:
|
||||
status = CLIENT_install(directory, sw_client, sw_force, inst_error);
|
||||
switch (status)
|
||||
{
|
||||
case FB_INSTALL_SAME_VERSION_FOUND :
|
||||
ib_printf("Existing %s (same version) found.\n", clientname);
|
||||
ib_printf("No update needed.\n");
|
||||
break;
|
||||
case FB_INSTALL_NEWER_VERSION_FOUND :
|
||||
ib_printf("Existing %s (newer version) found.\n", clientname);
|
||||
ib_printf("You can force replacing the DLL with -f[orce] switch.\n");
|
||||
ib_printf("Though this could break some other InterBase(R) "
|
||||
"or Firebird installation.\n");
|
||||
break;
|
||||
case FB_INSTALL_COPY_REQUIRES_REBOOT :
|
||||
ib_printf("%s has been scheduled for installation "
|
||||
"at the next system reboot.\n", clientname);
|
||||
break;
|
||||
case FB_SUCCESS :
|
||||
ib_printf("%s has been installed to the "
|
||||
"System directory.\n", clientname);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMAND_REMOVE:
|
||||
status = CLIENT_remove(directory, sw_client, sw_force, inst_error);
|
||||
switch (status)
|
||||
{
|
||||
case FB_INSTALL_FILE_NOT_FOUND :
|
||||
ib_printf("%s was not found in the System directory.\n",
|
||||
clientname);
|
||||
break;
|
||||
case FB_INSTALL_CANT_REMOVE_ALIEN_VERSION :
|
||||
ib_printf("The installed %s appears to be from an "
|
||||
"unsupported version.\n", clientname);
|
||||
ib_printf("It probably belongs to another version of "
|
||||
"Firebird or InterBase(R).\n");
|
||||
break;
|
||||
case FB_INSTALL_FILE_PROBABLY_IN_USE :
|
||||
ib_printf("The %s can't be removed. It is probably "
|
||||
"currently in use.\n", clientname);
|
||||
break;
|
||||
case FB_SUCCESS :
|
||||
ib_printf("The %s has been removed from the "
|
||||
"System directory.\n", clientname);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMAND_QUERY:
|
||||
ULONG verMS, verLS, sharedCount;
|
||||
status = CLIENT_query(sw_client, verMS, verLS, sharedCount, inst_error);
|
||||
switch (status)
|
||||
{
|
||||
case FB_INSTALL_FILE_NOT_FOUND :
|
||||
ib_printf("%s was not found in the System directory.\n",
|
||||
clientname);
|
||||
break;
|
||||
case FB_SUCCESS :
|
||||
ib_printf("Installed %s version : %u.%u.%u.%u "
|
||||
"(shared DLL count %d)\n", clientname,
|
||||
verMS >> 16, verMS & 0x0000ffff,
|
||||
verLS >> 16, verLS & 0x0000ffff,
|
||||
sharedCount);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case FB_INSTALL_COPY_REQUIRES_REBOOT :
|
||||
return -FB_INSTALL_COPY_REQUIRES_REBOOT;
|
||||
case FB_SUCCESS :
|
||||
return FINI_OK;
|
||||
default :
|
||||
return FINI_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static USHORT inst_error(ULONG status, const TEXT * string)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* g d s _ e r r o r
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Report an error and punt.
|
||||
*
|
||||
**************************************/
|
||||
TEXT buffer[512];
|
||||
SSHORT l;
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
// Allows to report non System errors
|
||||
ib_printf("%s\n", string);
|
||||
}
|
||||
else
|
||||
{
|
||||
ib_printf("Error %u occurred during \"%s\".\n", status, string);
|
||||
|
||||
if (!(l = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
status,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
NULL)))
|
||||
{
|
||||
ib_printf("Windows NT error %"SLONGFORMAT"\n", status);
|
||||
}
|
||||
else
|
||||
{
|
||||
CharToOem(buffer, buffer);
|
||||
ib_printf("%s", buffer); // '\n' is included in system messages
|
||||
}
|
||||
}
|
||||
return FB_FAILURE;
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* u s a g e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
*
|
||||
**************************************/
|
||||
|
||||
ib_printf("Usage:\n");
|
||||
ib_printf(" instclient i[nstall] [ -f[orce] ] library\n");
|
||||
ib_printf(" q[uery] library\n");
|
||||
ib_printf(" r[emove] library\n");
|
||||
ib_printf("\n");
|
||||
ib_printf(" where library is: f[bclient] | g[ds32] \n");
|
||||
ib_printf("\n");
|
||||
ib_printf(" This utility should be located and run from the 'bin' directory\n");
|
||||
ib_printf(" of your Firebird installation.\n");
|
||||
ib_printf(" '-z' can be used with any other option, prints version\n");
|
||||
ib_printf("\n");
|
||||
ib_printf("Purpose:\n");
|
||||
ib_printf(" This utility manages deployment of the Firebird client library \n");
|
||||
ib_printf(" into the Windows system directory. It caters for two installation\n");
|
||||
ib_printf(" scenarios:\n");
|
||||
ib_printf("\n");
|
||||
ib_printf(" Deployment of the native fbclient.dll.\n");
|
||||
ib_printf(" Deployment of gds32.dll to support legacy applications.\n");
|
||||
ib_printf("\n");
|
||||
ib_printf(" Version information and shared library counts are handled \n");
|
||||
ib_printf(" automatically. You may provide the -f[orce] option to override\n");
|
||||
ib_printf(" version checks.\n");
|
||||
ib_printf("\n");
|
||||
ib_printf(" Please, note that if you -f[orce] the installation, you might have\n");
|
||||
ib_printf(" to reboot the machine in order to finalize the copy and you might\n");
|
||||
ib_printf(" break some other Firebird or InterBase(R) version on the system.\n");
|
||||
|
||||
exit(FINI_ERROR);
|
||||
}
|
@ -58,13 +58,31 @@
|
||||
#define ARCH_SS 0
|
||||
#define ARCH_CS 1
|
||||
|
||||
// instclient constants
|
||||
#define CLIENT_NONE 0
|
||||
#define CLIENT_FB 1
|
||||
#define CLIENT_GDS 2
|
||||
|
||||
#define GDS32_NAME "GDS32.DLL"
|
||||
#define FBCLIENT_NAME "FBCLIENT.DLL"
|
||||
|
||||
// instsvc status codes
|
||||
#define IB_SERVICE_ALREADY_DEFINED 100
|
||||
#define IB_SERVICE_RUNNING 101
|
||||
#define FB_LOGON_SRVC_RIGHT_ALREADY_DEFINED 102
|
||||
#define FB_SERVICE_STATUS_RUNNING 100
|
||||
#define FB_SERVICE_STATUS_STOPPED 111
|
||||
#define FB_SERVICE_STATUS_PENDING 112
|
||||
#define FB_SERVICE_STATUS_NOT_INSTALLED 113
|
||||
#define FB_SERVICE_STATUS_UNKNOWN 114
|
||||
|
||||
#define IB_GUARDIAN_ALREADY_DEFINED 102
|
||||
#define IB_GUARDIAN_RUNNING 103
|
||||
|
||||
#define FB_LOGON_SRVC_RIGHT_ALREADY_DEFINED 104
|
||||
|
||||
#endif /* UTILITIES_INSTALL_NT_H */
|
||||
// instclient status codes
|
||||
#define FB_INSTALL_COPY_REQUIRES_REBOOT 200
|
||||
#define FB_INSTALL_SAME_VERSION_FOUND 201
|
||||
#define FB_INSTALL_NEWER_VERSION_FOUND 202
|
||||
#define FB_INSTALL_FILE_NOT_FOUND 203
|
||||
#define FB_INSTALL_CANT_REMOVE_ALIEN_VERSION 204
|
||||
#define FB_INSTALL_FILE_PROBABLY_IN_USE 205
|
||||
#define FB_INSTALL_SHARED_COUNT_ZERO 206
|
||||
|
||||
#endif /* _UTILITIES_INSTALL_NT_H_ */
|
||||
|
40
src/utilities/install/install_proto.h
Normal file
40
src/utilities/install/install_proto.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* PROGRAM: Windows NT GDS Client Library Installation
|
||||
* MODULE: install_proto.h
|
||||
* DESCRIPTION: Prototypes for GDS32.DLL installation functions
|
||||
*
|
||||
* The contents of this file are subject to the Initial Developer's
|
||||
* Public License Version 1.0 (the "License"); you may not use this
|
||||
* file except in compliance with the License. You may obtain a copy
|
||||
* of the License here:
|
||||
*
|
||||
* http://www.ibphoenix.com?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code is (C) 2003 Olivier Mascia.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Olivier Mascia.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _UTILITIES_INSTALL_PROTO_H_
|
||||
#define _UTILITIES_INSTALL_PROTO_H_
|
||||
|
||||
USHORT CLIENT_install(const TEXT* rootdirectory, USHORT client,
|
||||
bool sw_force, USHORT(*err_handler)(ULONG, const TEXT*));
|
||||
|
||||
USHORT CLIENT_remove(const TEXT* rootdirectory, USHORT client,
|
||||
bool sw_force, USHORT(*err_handler)(ULONG, const TEXT*));
|
||||
|
||||
USHORT CLIENT_query(USHORT client, ULONG& verMS, ULONG& verLS,
|
||||
ULONG& sharedCount, USHORT(*err_handler)(ULONG, const TEXT *));
|
||||
|
||||
#endif /* _UTILITIES_GDSCLIENT_PROTO_H_ */
|
@ -24,6 +24,9 @@
|
||||
#ifndef UTILITIES_SERVI_PROTO_H
|
||||
#define UTILITIES_SERVI_PROTO_H
|
||||
|
||||
// OM Jan '04 : Huh ? Who decided to drop the parameters names from these proto ?
|
||||
// Is there a consensus that removing them makes the code more self-documenting ?
|
||||
|
||||
USHORT SERVICES_install(SC_HANDLE, TEXT*, TEXT*, TEXT*, TEXT*, TEXT*, USHORT,
|
||||
TEXT*, TEXT*, USHORT (*)(SLONG, TEXT *, SC_HANDLE));
|
||||
|
||||
@ -33,6 +36,8 @@ USHORT SERVICES_start(SC_HANDLE, TEXT*, TEXT*, USHORT, USHORT (*)(SLONG, TEXT *,
|
||||
|
||||
USHORT SERVICES_stop(SC_HANDLE, TEXT*, TEXT*, USHORT (*)(SLONG, TEXT *, SC_HANDLE));
|
||||
|
||||
USHORT SERVICES_status(TEXT*);
|
||||
|
||||
USHORT SERVICES_grant_logon_right(TEXT*, USHORT (*)(SLONG, TEXT *, SC_HANDLE));
|
||||
|
||||
USHORT SERVICES_grant_access_rights(TEXT*, TEXT*, USHORT (*)(SLONG, TEXT *, SC_HANDLE));
|
||||
|
@ -149,6 +149,19 @@ USHORT SERVICES_remove(SC_HANDLE manager,
|
||||
|
||||
CloseServiceHandle(service);
|
||||
|
||||
// Let's loop until the service is actually confirmed deleted
|
||||
while (true)
|
||||
{
|
||||
service = OpenService(manager, service_name, GENERIC_READ);
|
||||
if (service == NULL)
|
||||
{
|
||||
if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) break;
|
||||
}
|
||||
else CloseServiceHandle(service);
|
||||
|
||||
Sleep(100); // A small nap is always good for health :)
|
||||
}
|
||||
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
@ -269,6 +282,55 @@ USHORT SERVICES_stop(SC_HANDLE manager,
|
||||
return FB_SUCCESS;
|
||||
}
|
||||
|
||||
USHORT SERVICES_status (TEXT* service_name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* S E R V I C E S _ s t a t u s
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Returns the Running/Stopped/Pending status of a service.
|
||||
* This API does not use an error handler because it has not real error
|
||||
* to ever report. For instance, a non-existing service is not reported as
|
||||
* an error, but as a status info through the function return value.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
SC_HANDLE manager = OpenSCManager(NULL, NULL, GENERIC_READ);
|
||||
if (manager == NULL)
|
||||
return FB_SERVICE_STATUS_UNKNOWN;
|
||||
|
||||
SC_HANDLE service = OpenService(manager, service_name, GENERIC_READ);
|
||||
if (service == NULL)
|
||||
{
|
||||
CloseServiceHandle(manager);
|
||||
return FB_SERVICE_STATUS_NOT_INSTALLED;
|
||||
}
|
||||
|
||||
SERVICE_STATUS service_status;
|
||||
if (!QueryServiceStatus(service, &service_status))
|
||||
{
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(manager);
|
||||
return FB_SERVICE_STATUS_UNKNOWN;
|
||||
}
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(manager);
|
||||
|
||||
USHORT status = FB_SERVICE_STATUS_UNKNOWN;
|
||||
switch (service_status.dwCurrentState)
|
||||
{
|
||||
case SERVICE_RUNNING : status = FB_SERVICE_STATUS_RUNNING; break;
|
||||
case SERVICE_STOPPED : status = FB_SERVICE_STATUS_STOPPED; break;
|
||||
case SERVICE_START_PENDING : /* fall over the next case */
|
||||
case SERVICE_STOP_PENDING : status = FB_SERVICE_STATUS_PENDING; break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
USHORT SERVICES_grant_logon_right(TEXT* account,
|
||||
USHORT(*err_handler)(SLONG, TEXT *, SC_HANDLE))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user