2020-05-27 12:09:57 -07:00
/**
* @ file Install . cpp
2022-01-18 22:38:56 +03:30
* @ author Sina Karvandi ( sina @ hyperdbg . org )
2020-05-27 12:09:57 -07:00
* @ brief Install functions
* @ details
* @ version 0.1
* @ date 2020 - 04 - 11
*
* @ copyright This project is released under the GNU Public License v3 .
*
*/
2022-05-04 16:38:21 -07:00
# include "pch.h"
2020-05-27 12:09:57 -07:00
/**
* @ brief Install driver
*
* @ param SC_HANDLE
* @ param LPCTSTR
* @ param LPCTSTR
* @ return BOOLEAN
*/
BOOLEAN
2021-03-22 18:19:39 +04:30
InstallDriver ( SC_HANDLE SchSCManager , LPCTSTR DriverName , LPCTSTR ServiceExe )
{
2021-10-31 21:47:02 +03:30
SC_HANDLE SchService ;
2023-03-22 17:45:52 +09:00
DWORD LastError ;
2020-05-27 12:09:57 -07:00
2021-03-22 18:19:39 +04:30
//
// NOTE: This creates an entry for a standalone driver. If this
// is modified for use with a driver that requires a Tag,
// Group, and/or Dependencies, it may be necessary to
// query the registry for existing driver information
2023-02-02 19:41:32 +09:00
// (in order to determine a unique Tag, etc.)
//
//
// Create a new a service object
//
2023-03-22 17:45:52 +09:00
SchService = CreateService ( SchSCManager , // handle of service control manager database
DriverName , // address of name of service to start
DriverName , // address of display name
SERVICE_ALL_ACCESS , // type of access to service
SERVICE_KERNEL_DRIVER , // type of service
SERVICE_DEMAND_START , // when to start service
SERVICE_ERROR_NORMAL , // severity if service fails to start
ServiceExe , // address of name of binary file
NULL , // service does not belong to a group
NULL , // no tag requested
NULL , // no dependency names
NULL , // use LocalSystem account
NULL // no password for service account
2023-02-02 19:41:32 +09:00
) ;
2023-03-22 17:45:52 +09:00
if ( SchService = = NULL )
{
2021-10-31 21:47:02 +03:30
LastError = GetLastError ( ) ;
2021-03-22 18:19:39 +04:30
2023-03-22 17:45:52 +09:00
if ( LastError = = ERROR_SERVICE_EXISTS )
{
2021-03-22 18:19:39 +04:30
//
2025-02-15 18:27:02 +01:00
// The service is already been created
2026-04-23 12:38:48 +00:00
// means that, the driver is previously installed
2025-02-15 18:27:02 +01:00
//
ShowMessages ( " the service (driver) already exists \n " ) ;
//
// We need to remove the old instance of the driver first
// Because the version of the driver might be different from the
// user-mode application
//
ShowMessages ( " trying to remove the old instance of the driver first \n " ) ;
//
// Stop the driver
//
ManageDriver ( DriverName , NULL , DRIVER_FUNC_STOP ) ;
//
// Remove the driver
//
if ( ManageDriver ( DriverName , NULL , DRIVER_FUNC_REMOVE ) )
{
ShowMessages ( " the old instance of the driver is removed successfully \n " ) ;
}
else
{
ShowMessages ( " err, failed to remove the old instance of the driver \n " ) ;
return FALSE ;
}
//
// Try to install the driver again
2021-03-22 18:19:39 +04:30
//
2025-02-15 18:27:02 +01:00
ShowMessages ( " installing the driver again \n " ) ;
if ( InstallDriver ( SchSCManager , DriverName , ServiceExe ) )
{
return TRUE ;
}
else
{
ShowMessages ( " err, failed to install the driver after removing the old instance \n " ) ;
return FALSE ;
}
2023-03-22 17:45:52 +09:00
}
else if ( LastError = = ERROR_SERVICE_MARKED_FOR_DELETE )
{
2021-03-22 18:19:39 +04:30
//
// Previous instance of the service is not fully deleted so sleep
2023-02-02 19:41:32 +09:00
// and try again
2021-03-22 18:19:39 +04:30
//
2021-10-31 21:47:02 +03:30
ShowMessages ( " err, previous instance of the service is not fully deleted. Try "
2021-03-22 18:19:39 +04:30
" again... \n " ) ;
return FALSE ;
2023-03-22 17:45:52 +09:00
}
else
{
2021-10-31 21:47:02 +03:30
ShowMessages ( " err, CreateService failed (%x) \n " , LastError ) ;
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Indicate an error
2021-03-22 18:19:39 +04:30
//
return FALSE ;
}
2020-05-27 12:09:57 -07:00
}
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Close the service object
2021-03-22 18:19:39 +04:30
//
2023-03-22 17:45:52 +09:00
if ( SchService )
{
2021-10-31 21:47:02 +03:30
CloseServiceHandle ( SchService ) ;
2021-03-22 18:19:39 +04:30
}
2020-05-27 12:09:57 -07:00
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Indicate success
2021-03-22 18:19:39 +04:30
//
return TRUE ;
2020-05-27 12:09:57 -07:00
}
/**
* @ brief Manage Driver
*
2022-04-13 12:45:39 +04:30
* @ param DriverName
* @ param ServiceName
* @ param Function
2020-05-27 12:09:57 -07:00
* @ return BOOLEAN
*/
BOOLEAN
2022-04-13 12:45:39 +04:30
ManageDriver ( LPCTSTR DriverName , LPCTSTR ServiceName , UINT16 Function )
2021-03-22 18:19:39 +04:30
{
2025-02-15 18:27:02 +01:00
SC_HANDLE SchSCManager ;
2023-03-22 17:45:52 +09:00
BOOLEAN Res = TRUE ;
2020-05-27 12:09:57 -07:00
//
2023-02-02 19:41:32 +09:00
// Insure (somewhat) that the driver and service names are valid
2020-05-27 12:09:57 -07:00
//
2025-02-15 18:27:02 +01:00
if ( ! DriverName | | ( Function = = DRIVER_FUNC_INSTALL & & ! ServiceName ) )
2023-03-22 17:45:52 +09:00
{
2021-04-11 22:21:22 +04:30
ShowMessages ( " invalid Driver or Service provided to ManageDriver() \n " ) ;
2020-05-27 12:09:57 -07:00
2021-03-22 18:19:39 +04:30
return FALSE ;
2020-05-27 12:09:57 -07:00
}
//
2023-02-02 19:41:32 +09:00
// Connect to the Service Control Manager and open the Services database
2020-05-27 12:09:57 -07:00
//
2025-02-15 18:27:02 +01:00
SchSCManager = OpenSCManager ( NULL , // local machine
2023-03-22 17:45:52 +09:00
NULL , // local database
SC_MANAGER_ALL_ACCESS // access required
2021-03-22 18:19:39 +04:30
) ;
2025-02-15 18:27:02 +01:00
if ( ! SchSCManager )
2023-03-22 17:45:52 +09:00
{
2021-09-30 12:31:51 +03:30
ShowMessages ( " err, OpenSCManager failed (%x) \n " , GetLastError ( ) ) ;
2021-03-22 18:19:39 +04:30
return FALSE ;
}
2020-05-27 12:09:57 -07:00
//
2023-02-02 19:41:32 +09:00
// Do the requested function
2020-05-27 12:09:57 -07:00
//
2023-03-22 17:45:52 +09:00
switch ( Function )
{
2021-03-22 18:19:39 +04:30
case DRIVER_FUNC_INSTALL :
//
2023-02-02 19:41:32 +09:00
// Install the driver service
2021-03-22 18:19:39 +04:30
//
2021-04-02 01:12:32 +04:30
2025-02-15 18:27:02 +01:00
if ( InstallDriver ( SchSCManager , DriverName , ServiceName ) )
2023-03-22 17:45:52 +09:00
{
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Start the driver service (i.e. start the driver)
2021-03-22 18:19:39 +04:30
//
2025-02-15 18:27:02 +01:00
Res = StartDriver ( SchSCManager , DriverName ) ;
2023-03-22 17:45:52 +09:00
}
else
{
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Indicate an error
2021-03-22 18:19:39 +04:30
//
2021-10-31 21:47:02 +03:30
Res = FALSE ;
2021-03-22 18:19:39 +04:30
}
break ;
2021-04-02 01:12:32 +04:30
case DRIVER_FUNC_STOP :
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Stop the driver
2021-03-22 18:19:39 +04:30
//
2025-02-15 18:27:02 +01:00
Res = StopDriver ( SchSCManager , DriverName ) ;
2021-04-02 01:12:32 +04:30
break ;
case DRIVER_FUNC_REMOVE :
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Remove the driver service
2021-03-22 18:19:39 +04:30
//
2025-02-15 18:27:02 +01:00
Res = RemoveDriver ( SchSCManager , DriverName ) ;
2021-03-22 18:19:39 +04:30
break ;
default :
2023-02-02 19:41:32 +09:00
ShowMessages ( " unknown ManageDriver() function \n " ) ;
2021-03-22 18:19:39 +04:30
2021-10-31 21:47:02 +03:30
Res = FALSE ;
2021-03-22 18:19:39 +04:30
break ;
}
2020-05-27 12:09:57 -07:00
//
2023-02-02 19:41:32 +09:00
// Close handle to service control manager
2020-05-27 12:09:57 -07:00
//
2025-02-15 18:27:02 +01:00
if ( SchSCManager )
2023-03-22 17:45:52 +09:00
{
2025-02-15 18:27:02 +01:00
CloseServiceHandle ( SchSCManager ) ;
2021-03-22 18:19:39 +04:30
}
2020-05-27 12:09:57 -07:00
2021-10-31 21:47:02 +03:30
return Res ;
2020-05-27 12:09:57 -07:00
}
/**
* @ brief Remove Driver
*
* @ param SC_HANDLE
* @ param LPCTSTR
* @ return BOOLEAN
*/
BOOLEAN
2021-03-22 18:19:39 +04:30
RemoveDriver ( SC_HANDLE SchSCManager , LPCTSTR DriverName )
{
2021-10-31 21:47:02 +03:30
SC_HANDLE SchService ;
2023-03-22 17:45:52 +09:00
BOOLEAN Res ;
2020-05-27 12:09:57 -07:00
//
2021-04-02 01:12:32 +04:30
// Open the handle to the existing service
2020-05-27 12:09:57 -07:00
//
2021-10-31 21:47:02 +03:30
SchService = OpenService ( SchSCManager , DriverName , SERVICE_ALL_ACCESS ) ;
2020-05-27 12:09:57 -07:00
2023-03-22 17:45:52 +09:00
if ( SchService = = NULL )
{
2021-09-30 12:31:51 +03:30
ShowMessages ( " err, OpenService failed (%x) \n " , GetLastError ( ) ) ;
2021-03-22 18:19:39 +04:30
//
2021-04-02 01:12:32 +04:30
// Indicate error
2021-03-22 18:19:39 +04:30
//
return FALSE ;
}
2020-05-27 12:09:57 -07:00
//
2021-04-02 01:12:32 +04:30
// Mark the service for deletion from the service control manager database
2020-05-27 12:09:57 -07:00
//
2023-03-22 17:45:52 +09:00
if ( DeleteService ( SchService ) )
{
2021-03-22 18:19:39 +04:30
//
2021-04-02 01:12:32 +04:30
// Indicate success
2021-03-22 18:19:39 +04:30
//
2021-10-31 21:47:02 +03:30
Res = TRUE ;
2023-03-22 17:45:52 +09:00
}
else
{
2021-09-30 12:31:51 +03:30
ShowMessages ( " err, DeleteService failed (%x) \n " , GetLastError ( ) ) ;
2021-03-22 18:19:39 +04:30
//
2021-04-02 01:12:32 +04:30
// Indicate failure. Fall through to properly close the service handle
2021-03-22 18:19:39 +04:30
//
2021-10-31 21:47:02 +03:30
Res = FALSE ;
2021-03-22 18:19:39 +04:30
}
2020-05-27 12:09:57 -07:00
//
2021-04-02 01:12:32 +04:30
// Close the service object
2020-05-27 12:09:57 -07:00
//
2023-03-22 17:45:52 +09:00
if ( SchService )
{
2021-10-31 21:47:02 +03:30
CloseServiceHandle ( SchService ) ;
2021-03-22 18:19:39 +04:30
}
2020-05-27 12:09:57 -07:00
2021-10-31 21:47:02 +03:30
return Res ;
2020-05-27 12:09:57 -07:00
}
/**
* @ brief Start Driver
*
* @ param SC_HANDLE
* @ param LPCTSTR
* @ return BOOLEAN
*/
BOOLEAN
2021-03-22 18:19:39 +04:30
StartDriver ( SC_HANDLE SchSCManager , LPCTSTR DriverName )
{
2024-03-15 13:49:02 +09:00
SC_HANDLE SchService ;
DWORD LastError ;
BOOLEAN Status = TRUE ;
2020-05-27 12:09:57 -07:00
//
2023-02-02 19:41:32 +09:00
// Open the handle to the existing service
2020-05-27 12:09:57 -07:00
//
2021-10-31 21:47:02 +03:30
SchService = OpenService ( SchSCManager , DriverName , SERVICE_ALL_ACCESS ) ;
2020-05-27 12:09:57 -07:00
2023-03-22 17:45:52 +09:00
if ( SchService = = NULL )
{
2021-09-30 12:31:51 +03:30
ShowMessages ( " err, OpenService failed (%x) \n " , GetLastError ( ) ) ;
2020-05-27 12:09:57 -07:00
2021-03-22 18:19:39 +04:30
//
2021-04-02 01:12:32 +04:30
// Indicate failure
2021-03-22 18:19:39 +04:30
//
return FALSE ;
2020-05-27 12:09:57 -07:00
}
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Start the execution of the service (i.e. start the driver)
2021-03-22 18:19:39 +04:30
//
2021-10-31 21:47:02 +03:30
if ( ! StartService ( SchService , // service identifier
2023-03-22 17:45:52 +09:00
0 , // number of arguments
NULL // pointer to arguments
) )
{
2021-10-31 21:47:02 +03:30
LastError = GetLastError ( ) ;
2021-03-22 18:19:39 +04:30
2023-03-22 17:45:52 +09:00
if ( LastError = = ERROR_SERVICE_ALREADY_RUNNING )
{
2021-03-22 18:19:39 +04:30
//
2021-04-02 01:12:32 +04:30
// Ignore this error
2021-03-22 18:19:39 +04:30
//
2023-03-22 17:45:52 +09:00
}
else if ( LastError = = ERROR_PATH_NOT_FOUND )
{
2021-10-31 21:47:02 +03:30
//
// Driver not found, or anti-virus limits the access to it
//
ShowMessages ( " err, path to the driver not found, or the access to the driver file is limited \n " ) ;
2025-02-15 18:27:02 +01:00
ShowMessages ( " most of the time, it's because anti-virus software is not finished scanning the drivers, "
" so, if you try to load the driver again (re-enter the previous command), the problem will be solved \n " ) ;
2021-10-31 21:47:02 +03:30
//
// Indicate failure
//
Status = FALSE ;
2023-03-22 17:45:52 +09:00
}
else if ( LastError = = ERROR_INVALID_IMAGE_HASH )
{
2021-03-22 18:19:39 +04:30
ShowMessages (
2021-10-31 21:47:02 +03:30
" err, failed loading driver \n "
" it's because either the driver signature enforcement is enabled or HVCI prevents the driver from loading \n "
" you should disable the driver signature enforcement by attaching WinDbg or from the boot menu \n "
" if the driver signature enforcement is disabled, HVCI might prevent the driver from loading \n "
" HyperDbg is not compatible with Virtualization Based Security (VBS) \n "
" please follow the instructions from: https://docs.hyperdbg.org/getting-started/build-and-install \n " ) ;
2021-03-22 18:19:39 +04:30
//
2021-04-02 01:12:32 +04:30
// Indicate failure. Fall through to properly close the service handle
2021-03-22 18:19:39 +04:30
//
2021-04-02 01:12:32 +04:30
Status = FALSE ;
2023-03-22 17:45:52 +09:00
}
else
{
2021-10-31 21:47:02 +03:30
ShowMessages ( " err, StartService failure (%x) \n " , LastError ) ;
2021-03-22 18:19:39 +04:30
//
2021-04-02 01:12:32 +04:30
// Indicate failure. Fall through to properly close the service handle
2021-03-22 18:19:39 +04:30
//
2021-04-02 01:12:32 +04:30
Status = FALSE ;
2021-03-22 18:19:39 +04:30
}
}
2020-05-27 12:09:57 -07:00
2021-03-22 18:19:39 +04:30
//
2021-04-02 01:12:32 +04:30
// Close the service object
2021-03-22 18:19:39 +04:30
//
2023-03-22 17:45:52 +09:00
if ( SchService )
{
2021-10-31 21:47:02 +03:30
CloseServiceHandle ( SchService ) ;
2021-03-22 18:19:39 +04:30
}
2020-05-27 12:09:57 -07:00
2021-04-02 01:12:32 +04:30
return Status ;
2020-05-27 12:09:57 -07:00
}
/**
* @ brief Stop driver
*
* @ param SC_HANDLE
* @ param LPCTSTR
* @ return BOOLEAN
*/
BOOLEAN
2021-03-22 18:19:39 +04:30
StopDriver ( SC_HANDLE SchSCManager , LPCTSTR DriverName )
{
2023-03-22 17:45:52 +09:00
BOOLEAN Res = TRUE ;
SC_HANDLE SchService ;
2021-03-22 18:19:39 +04:30
SERVICE_STATUS serviceStatus ;
2020-05-27 12:09:57 -07:00
//
2023-02-02 19:41:32 +09:00
// Open the handle to the existing service
2020-05-27 12:09:57 -07:00
//
2021-10-31 21:47:02 +03:30
SchService = OpenService ( SchSCManager , DriverName , SERVICE_ALL_ACCESS ) ;
2020-05-27 12:09:57 -07:00
2023-03-22 17:45:52 +09:00
if ( SchService = = NULL )
{
2021-09-30 12:31:51 +03:30
ShowMessages ( " err, OpenService failed (%x) \n " , GetLastError ( ) ) ;
2020-05-27 12:09:57 -07:00
2021-03-22 18:19:39 +04:30
return FALSE ;
}
2020-05-27 12:09:57 -07:00
//
2023-02-02 19:41:32 +09:00
// Request that the service stop
2020-05-27 12:09:57 -07:00
//
2023-03-22 17:45:52 +09:00
if ( ControlService ( SchService , SERVICE_CONTROL_STOP , & serviceStatus ) )
{
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Indicate success
2021-03-22 18:19:39 +04:30
//
2021-10-31 21:47:02 +03:30
Res = TRUE ;
2023-03-22 17:45:52 +09:00
}
else
{
2025-02-24 15:05:18 +01:00
ShowMessages ( " warning, failed to stop the driver. Possible reasons include the driver not currently running or an unsuccessful unload from a previous run. "
" This is not an error, HyperDbg tries to remove the previous driver and load it again (%x) \n " ,
GetLastError ( ) ) ;
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Indicate failure. Fall through to properly close the service handle
2021-03-22 18:19:39 +04:30
//
2021-10-31 21:47:02 +03:30
Res = FALSE ;
2021-03-22 18:19:39 +04:30
}
2020-05-27 12:09:57 -07:00
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Close the service object
2021-03-22 18:19:39 +04:30
//
2023-03-22 17:45:52 +09:00
if ( SchService )
{
2021-10-31 21:47:02 +03:30
CloseServiceHandle ( SchService ) ;
2021-03-22 18:19:39 +04:30
}
2020-05-27 12:09:57 -07:00
2021-10-31 21:47:02 +03:30
return Res ;
2020-05-27 12:09:57 -07:00
}
/**
2024-06-11 16:01:07 +09:00
* @ brief Setup file name
2020-05-27 12:09:57 -07:00
*
2024-06-11 16:01:07 +09:00
* @ param FileName
* @ param FileLocation
2023-02-02 19:41:32 +09:00
* @ param BufferLength
2024-06-11 19:13:37 +09:00
* @ param CheckFileExists
2023-02-02 19:41:32 +09:00
*
2020-05-27 12:09:57 -07:00
* @ return BOOLEAN
*/
BOOLEAN
2024-06-11 16:01:07 +09:00
SetupPathForFileName ( const CHAR * FileName ,
_Inout_updates_bytes_all_ ( BufferLength ) PCHAR FileLocation ,
2024-06-11 19:13:37 +09:00
ULONG BufferLength ,
BOOLEAN CheckFileExists )
2021-03-22 18:19:39 +04:30
{
2023-03-22 17:45:52 +09:00
HANDLE FileHandle ;
2024-06-11 16:01:07 +09:00
DWORD FileLocLen = 0 ;
HMODULE ProcHandle = GetModuleHandle ( NULL ) ;
2026-05-31 18:34:03 +02:00
CHAR * Pos ;
2020-05-27 12:09:57 -07:00
2021-03-22 18:19:39 +04:30
//
// Get the current directory.
//
2020-05-27 12:09:57 -07:00
2021-03-22 18:19:39 +04:30
/*
2020-08-28 04:03:12 -07:00
//
// We use the location of running exe instead of
// finding driver based on current directory
//
2024-06-11 16:01:07 +09:00
FileLocLen = GetCurrentDirectory ( BufferLength , DriverLocation ) ;
2020-05-27 12:09:57 -07:00
2024-06-11 16:01:07 +09:00
if ( FileLocLen = = 0 ) {
2020-05-27 12:09:57 -07:00
2021-09-30 12:31:51 +03:30
ShowMessages ( " err, GetCurrentDirectory failed (%x) \n " , GetLastError ( ) ) ;
2020-05-27 12:09:57 -07:00
return FALSE ;
}
2020-08-28 04:03:12 -07:00
*/
2024-06-11 16:01:07 +09:00
GetModuleFileName ( ProcHandle , FileLocation , BufferLength ) ;
2021-03-22 18:19:39 +04:30
2024-06-11 16:01:07 +09:00
Pos = strrchr ( FileLocation , ' \\ ' ) ;
2023-03-22 17:45:52 +09:00
if ( Pos ! = NULL )
{
2021-03-22 18:19:39 +04:30
//
// this will put the null terminator here. you can also copy to
// another string if you want, we can also use PathCchRemoveFileSpec
//
* Pos = ' \0 ' ;
}
2020-08-28 04:03:12 -07:00
//
2023-02-02 19:41:32 +09:00
// Setup path name to driver file
2020-08-28 04:03:12 -07:00
//
2021-03-22 18:19:39 +04:30
if ( FAILED (
2024-06-11 16:01:07 +09:00
StringCbCat ( FileLocation , BufferLength , " \\ " ) ) )
2023-03-22 17:45:52 +09:00
{
2023-02-02 19:41:32 +09:00
return FALSE ;
}
if ( FAILED (
2024-06-11 16:01:07 +09:00
StringCbCat ( FileLocation , BufferLength , FileName ) ) )
2023-03-22 17:45:52 +09:00
{
2021-03-22 18:19:39 +04:30
return FALSE ;
}
2020-05-27 12:09:57 -07:00
2024-06-11 19:13:37 +09:00
if ( CheckFileExists )
2023-03-22 17:45:52 +09:00
{
2021-03-22 18:19:39 +04:30
//
2024-06-11 19:13:37 +09:00
// ensure file is in the specified directory
2021-03-22 18:19:39 +04:30
//
2024-06-11 19:13:37 +09:00
if ( ( FileHandle = CreateFile ( FileLocation , GENERIC_READ , 0 , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL ) ) = = INVALID_HANDLE_VALUE )
{
ShowMessages ( " err, target file is not loaded \n " ) ;
2020-05-27 12:09:57 -07:00
2024-06-11 19:13:37 +09:00
//
// Indicate failure
//
return FALSE ;
}
//
// Close open file handle
//
if ( FileHandle )
{
CloseHandle ( FileHandle ) ;
}
2021-03-22 18:19:39 +04:30
}
2020-05-27 12:09:57 -07:00
2021-03-22 18:19:39 +04:30
//
2023-02-02 19:41:32 +09:00
// Indicate success
2021-03-22 18:19:39 +04:30
//
return TRUE ;
2020-05-27 12:09:57 -07:00
}