예제 #1
0
//
// Deferred Custom Action
//
//
// CustomActionData: 
// <ierrordialog>|<hardware_id>|<inf_path>|<regpath>|<regvalue>
//
//        
NC_DLLSPEC 
UINT 
NC_CALLSPEC 
NcaMsiUpdateOrInstallPnpDevice(MSIHANDLE hInstall)
{
	RUN_MODE_TRACE(hInstall);
	pMsiIncrementProgressBar(hInstall, 10);

	UINT uiReturn = 0;

	INT  iErrorDlg = 0;
	LPCTSTR pszHardwareID = NULL;
	LPCTSTR pszInfPath = NULL;
	LPCTSTR pszRegPath = NULL;
	LPCTSTR pszRegValue = NULL;

	CADParser parser;
	parser.AddToken<INT>(iErrorDlg);
	parser.AddToken<LPCTSTR>(pszHardwareID);
	parser.AddToken<LPCTSTR>(pszInfPath);
	parser.AddToken<LPCTSTR>(pszRegPath);
	parser.AddToken<LPCTSTR>(pszRegValue);
	DWORD nTokens = parser.Parse(hInstall);

	if (parser.GetTokenCount() != nTokens) 
	{
		MSILOGERR(_T("Cannot parse tokens"));
		return ERROR_INSTALL_FAILURE;
	}

	TCHAR szInstalledInf[MAX_PATH] = {0};
	BOOL bRebootRequired = FALSE;
	BOOL fSuccess = FALSE;
	BOOL fUpdateExisting = FALSE;

	while (TRUE) 
	{
		bRebootRequired = FALSE;
		//
		// Specifying INSTALLFLAG_FORCE will overwrite the
		// existing device driver with the current one
		// irrespective of existence of higher version
		//
		fUpdateExisting = NdasDiFindExistingDevice(
			NULL, 
			pszHardwareID, 
			FALSE);

		if (fUpdateExisting)
		{
			fSuccess = NdasDiUpdateDeviceDriver(
				NULL, 
				pszInfPath, 
				pszHardwareID, 
				INSTALLFLAG_FORCE, 
				&bRebootRequired);

			if (!fSuccess)
			{
				MSILOGERR_PROC(_T("NdasDiUpdateDeviceDriver"));
			}

		}
		else
		{
			MSILOGERR_PROC(_T("NdasDiFindExistingDevice"));

			fSuccess = NdasDiInstallRootEnumeratedDevice(
				NULL,
				pszInfPath,
				pszHardwareID,
				INSTALLFLAG_FORCE,
				&bRebootRequired);

			if (!fSuccess)
			{
				MSILOGERR_PROC(_T("NdasDiInstallRootEnumeratedDevice"));
			}

		}

		if (!fSuccess) 
		{

			UINT uiResponse = pMsiErrorMessageBox(hInstall, iErrorDlg);

			// 0, IDABORT, IDRETRY, IDIGNORE
			if (IDABORT == uiResponse) 
			{
				return ERROR_INSTALL_FAILURE;
			} 
			else if (IDRETRY == uiResponse) 
			{
				continue;
			}
			else if (IDIGNORE == uiResponse) 
			{
			}
		}

		break;
	}

	if (bRebootRequired)
	{
		(void) pMsiScheduleRebootForDeferredCA(hInstall);
	}

	//
	// The following actions are non-critical ones
	//

	if (fSuccess) 
	{
		//
		// set the registry value
		//
		if (!fUpdateExisting && _T('\0') != szInstalledInf[0]) 
		{
			fSuccess = pSetInstalledPath(
				hInstall,
				HKEY_LOCAL_MACHINE, 
				pszRegPath, 
				pszRegValue, 
				szInstalledInf);

			if (!fSuccess) 
			{
				MSILOGERR_PROC(_T("pSetInstalledPath"));
			}
		}
	}

	return ERROR_SUCCESS;
}
예제 #2
0
int pnpdevinst(int argc, LPTSTR *argv)
{
	typedef enum {
		DEV_INSTALL,
		DEV_UPDATE,
		DEV_REMOVE,
		DEV_COPYINF,
		DEV_FIND,
		DEV_UNINSTALLINF
	} DEV_COMMAND_TYPE;

	struct {
		DEV_COMMAND_TYPE type;
		LPCTSTR cmd; 
		int argc; 
		BOOL op; 
	} opts[] = 
	{ 
		{ DEV_INSTALL, L"install", 2, FALSE}, 
		{ DEV_UPDATE, L"update", 2, FALSE},
		{ DEV_REMOVE, L"remove", 1, TRUE}, 
		{ DEV_COPYINF, L"copyinf", 1, FALSE},
		{ DEV_FIND, L"find", 1, TRUE},
		{ DEV_UNINSTALLINF, L"uninstallinf", 1, FALSE}
	};

	DEV_COMMAND_TYPE CmdType;

	const DWORD nopts = RTL_NUMBER_OF(opts);

	DWORD i = 0;
	for (; i < nopts; ++i) {
		if (lstrcmpi(opts[i].cmd, argv[0]) == 0) {
			if ((argc - 1) == opts[i].argc ||
				(opts[i].op && (argc - 1) >= opts[i].argc)) 
			{
				CmdType = opts[i].type;
			} else {
				_ftprintf(stderr, _T("Invalid command arguments.\n"));
				return 254;
			}
			break;
		}
	}

	if (i == nopts) {
		_ftprintf(stderr, _T("Invalid command.\n"));
		return 254;
	}

	BOOL bRebootRequired;
	BOOL bPresentOnly = TRUE;

	if (DEV_INSTALL == CmdType) {

		BOOL fSuccess = NdasDiInstallRootEnumeratedDevice(
			NULL, 
			argv[1], 
			argv[2],
			INSTALLFLAG_FORCE,
			&bRebootRequired);
		if (!fSuccess) {
			printErrorText();
			return 255;
		} else {
			_ftprintf(stdout, _T("Installation is done.%s"),
				(bRebootRequired) ? _T(" Reboot required.") : _T(""));
			return (bRebootRequired) ? 1 : 0;
		}

	} else if (DEV_UPDATE == CmdType) {

		BOOL fSuccess = NdasDiUpdateDeviceDriver(
			NULL,
			argv[1],
			argv[2],
			INSTALLFLAG_FORCE,
			&bRebootRequired);
		if (!fSuccess) {
			printErrorText();
			return 255;
		} else {
			_ftprintf(stdout, _T("Update is done.%s"),
				(bRebootRequired) ? _T(" Reboot required.") :  _T(""));
			return (bRebootRequired) ? 1 : 0;
		}

	} else if (DEV_REMOVE == CmdType) {

		if (argc > 2 && 0 == lstrcmpi(argv[2], _T("all"))) {
			bPresentOnly = FALSE;
		}

		DWORD dwRemoved = 0;
		BOOL fSuccess = NdasDiRemoveDevice(
			NULL,
			argv[1], 
			bPresentOnly,
			&dwRemoved,
			&bRebootRequired,
			RemoveErrorCallback,
			NULL);
		if (!fSuccess) {
			printErrorText();
			return 255;
		} else {
			printErrorText();
			_ftprintf(stdout, _T("Removal is done for %d devices.%s"),
				dwRemoved,
				(bRebootRequired) ? _T(" Reboot required.") : _T(""));
			return 0;
		}

	} else if (DEV_COPYINF == CmdType) {

		TCHAR szOemInf[MAX_PATH + 1];

		BOOL fSuccess = NdasDiCopyOEMInf(
			argv[1], 
			0,
			szOemInf,
			MAX_PATH,
			NULL,
			NULL);

		if (!fSuccess) {
			printErrorText();
			return 255;
		} else {
			_ftprintf(stdout, _T("Copied to %s\n"), szOemInf);
			return 0;
		}

	} else if (DEV_FIND == CmdType) {

		LPCTSTR szHardwareID = argv[1];

		if (argc > 2 && 0 == lstrcmpi(argv[2], _T("all"))) {
			bPresentOnly = FALSE;
		}

		BOOL fSuccess = NdasDiFindExistingDevice(
			NULL,
			szHardwareID,
			bPresentOnly);

		if (!fSuccess) {
			if (ERROR_NO_MORE_ITEMS == GetLastError()) {
				_ftprintf(stdout, _T("Device not found.\n"));
				return 1;
			} else {
				printErrorText();
				return 255;
			}
		} else {
			_ftprintf(stdout, _T("Device found.\n"));
			return 0;
		}

	} else if (DEV_UNINSTALLINF == CmdType) {
		
		size_t cchHardwareIDs = ::lstrlen(argv[1]) + 2; // plus additional null

		LPTSTR mszHardwareIDs = (LPTSTR) ::HeapAlloc(
			::GetProcessHeap(),
			HEAP_ZERO_MEMORY,
			cchHardwareIDs * sizeof(TCHAR));
		_ASSERTE(NULL != mszHardwareIDs);

		HRESULT hr = ::StringCchCopy(mszHardwareIDs, cchHardwareIDs, argv[1]);
		_ASSERTE(SUCCEEDED(hr));

		// replaces , to _T('\0')
		PTCHAR pch = mszHardwareIDs;
		for (size_t i = 0; i < cchHardwareIDs; ++i, ++pch) {
			if (_T(',') == *pch) {
				*pch = _T('\0');
			}
		}

		_tprintf(_T("%s\n"), mszHardwareIDs);

		BOOL fSuccess = NdasDiDeleteOEMInf(
			_T("oem*.inf"),
			mszHardwareIDs,
			0x0001,
			DeleteOEMInfCallback,
			NULL);

		::HeapFree(::GetProcessHeap(), 0, mszHardwareIDs);

		return 0;

	} else {
		_ftprintf(stderr, _T("Unknown command.\n"));
		return 254;
	}
}