CnCrypt代码 之 比较靠谱的临时驱动挂载和卸载方法

CnCrypt便携版采用的驱动挂载和卸载方法,驱动启动之后直接添加删除标记,当驱动停止后,驱动就会自动卸载。


// Install and start driver service and mark it for removal (non-install mode)
int  DriverLoad()
{
	SC_HANDLE		hManager = NULL, hService = NULL;
	WCHAR			szDriverPath[CC_LONG_PATH + 1];
	BOOL			bResult = FALSE;
	DWORD			dwStartType;

	if (ReadLocalMachineRegistryDword(L"SYSTEM\\CurrentControlSet\\Services\\CnCrypt", L"Start", &dwStartType)
		&& (dwStartType == SERVICE_SYSTEM_START || dwStartType == SERVICE_BOOT_START))
	{
		return ERR_PARAMETER_INCORRECT;
	}

	GetModPath(szDriverPath, ARRAYSIZE(szDriverPath));
	wcscat(szDriverPath, !OSVersion::Is64BitOs() ? L"CnCrypt.sys" : L"CnCrypt-x64.sys");
	if (!FileExists(szDriverPath))
	{
		Error("DRIVER_NOT_FOUND");
		return ERR_DONT_REPORT;
	}

	hManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (hManager == NULL)
	{
		if (GetLastError() == ERROR_ACCESS_DENIED)
		{
			Error("ADMIN_PRIVILEGES_DRIVER");
			return ERR_DONT_REPORT;
		}

		return ERR_OS_ERROR;
	}

	// Remove stale service (driver is not loaded but service exists)
	hService = OpenService(hManager, L"CnCrypt", SERVICE_ALL_ACCESS);
	if (hService != NULL)
	{
		DeleteService(hService);
		CloseServiceHandle(hService);
		hService = NULL;
		Sleep(500);
	}

	hService = CreateService(hManager, L"CnCrypt", L"CnCrypt",
		SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
		szDriverPath, NULL, NULL, NULL, NULL, NULL);
	if (hService == NULL)
	{
		goto error;
	}
	CloseServiceHandle(hService);
	hService = NULL;

	hService = OpenService(hManager, L"CnCrypt", SERVICE_ALL_ACCESS);
	if (hService == NULL)
	{
		goto error;
	}

	bResult = StartService(hService, 0, NULL);
	if (!bResult)
	{
		goto error;
	}

error:
	DWORD dwError = GetLastError();
	if (hService != NULL)
	{
		// 驱动停止后会自动删除
		DeleteService(hService);
		CloseServiceHandle(hService);
	}

	if (hManager != NULL)
	{
		CloseServiceHandle(hManager);
	}
	SetLastError(dwError);
	return !bResult ? ERR_OS_ERROR : ERROR_SUCCESS;
}


BOOL DriverUnload()
{
	int		iRefCount;
	int		iVolumesMounted;
	BOOL	bResult;

	SC_HANDLE hManager, hService = NULL;
	SERVICE_STATUS ssStatus;
	int		nTimes;
	BOOL	bDriverUnloaded = FALSE;

	if (g_hDriver == INVALID_HANDLE_VALUE)
	{
		return TRUE;
	}

	try
	{
		if (BootEncryption(NULL).GetStatus().bDeviceFilterActive)
		{
			return FALSE;
		}
	}
	catch (...) {}

	// Test for mounted volumes
	bResult = GetVolumeMounted(g_hDriver, &iVolumesMounted);
	if (!bResult)
	{
		return TRUE;
	}

	if (iVolumesMounted != 0)
	{
		return FALSE;
	}

	// Test for any applications attached to driver
	iRefCount = GetDriverRefCount(g_hDriver);
	if (iRefCount > 1)
	{
		return FALSE;
	}

	CloseHandle(g_hDriver);
	g_hDriver = INVALID_HANDLE_VALUE;

	// Stop driver service
	hManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (hManager == NULL)
	{
		goto error;
	}

	hService = OpenService(hManager, L"CnCrypt", SERVICE_ALL_ACCESS);
	if (hService == NULL)
	{
		goto error;
	}
	BOOL bControlServiceStop = FALSE;
	do
	{
#define WAIT_PERIOD 3
		for (nTimes = 0; nTimes < WAIT_PERIOD; nTimes++)
		{
			bResult = QueryServiceStatus(hService, &ssStatus);
			if (!bResult)
			{
				goto error;
			}

			if (ssStatus.dwCurrentState != SERVICE_START_PENDING &&
				ssStatus.dwCurrentState != SERVICE_STOP_PENDING &&
				ssStatus.dwCurrentState != SERVICE_CONTINUE_PENDING)
			{
				break;
			}

			Sleep(1000);
		}
		if (!bControlServiceStop)
		{
			if (ssStatus.dwCurrentState != SERVICE_STOPPED)
			{
				bResult = ControlService(hService, SERVICE_CONTROL_STOP, &ssStatus);
				if (!bResult)
				{
					goto error;
				}
			}
			else
			{
				break;
			}
			bControlServiceStop = TRUE;
		}
		else
		{
			if (ssStatus.dwCurrentState != SERVICE_STOPPED && ssStatus.dwCurrentState != SERVICE_STOP_PENDING)
			{
				goto error;
			}
			break;
		}
	} while (TRUE);

	bDriverUnloaded = TRUE;

error:
	if (hService != NULL)
	{
		CloseServiceHandle(hService);
	}

	if (hManager != NULL)
	{
		CloseServiceHandle(hManager);
	}

	return bDriverUnloaded;
}


你可能感兴趣的:(CnCrypt代码 之 比较靠谱的临时驱动挂载和卸载方法)