8
0
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:
epocman 2004-01-03 12:20:08 +00:00
parent 26af0411a9
commit a75b48c6a8
10 changed files with 1524 additions and 9 deletions

View File

@ -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

View File

@ -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>

View 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

View 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>

View 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
//

View 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);
}

View File

@ -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_ */

View 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_ */

View File

@ -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));

View File

@ -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))
{