示例#1
0
void CUpgradeDialog::OnOrderbyphone()
{
	// Update the product items with the selection flags from the list box.
	
	m_ProductList.UpdateProductItems();
	
	if (GetApp()->Offer()->CountProductFlags(PRODUCT_ITEM_Selected) == 0)
	{
		AfxMessageBox(IDS_NO_ITEMS_SELECTED_PHONE);
		return;
	}

	CInstallInfo Info;

	COrderByPhoneDialog Dialog(&Info, this);
	Dialog.m_pOrderForm = this;
	Dialog.SetTaxIndex(m_TaxList.GetCurSel());
	if (Dialog.DoModal() == IDOK)
	{
		m_ProductList.DisableLicensedItems();
		UpdateDialog();
		OnInstall();
	}
	
	UpdateDialog();
}
示例#2
0
文件: boinccas.cpp 项目: Ashod/Boinc
/////////////////////////////////////////////////////////////////////
// 
// Function:    Execute
//
// Description: 
//
/////////////////////////////////////////////////////////////////////
UINT BOINCCABase::Execute()
{
    UINT    uiReturnValue = 0;

    OnInitialize();

    if      ( TRUE == MsiGetMode( m_hMSIHandle, MSIRUNMODE_SCHEDULED ) )
    {
        uiReturnValue = OnInstall();
    }
    else if ( TRUE == MsiGetMode( m_hMSIHandle, MSIRUNMODE_COMMIT ) )
    {
        uiReturnValue = OnCommit();
    }
    else if ( TRUE == MsiGetMode( m_hMSIHandle, MSIRUNMODE_ROLLBACK ) )
    {
        uiReturnValue = OnRollback();
    }
    else
    {
        uiReturnValue = OnExecution();
    }

    OnCleanup();

    return uiReturnValue;
}
示例#3
0
    int win_svc_base::Main( int argc, char * argv[] )
    {
        //////////////////////////////////////////////////////////////////////////
        /// 命令行参数解析
        boost::program_options::options_description opts;
        opts.add_options()
            ("help", "options: --install --uninstall")
            ("install", "")
            ("uninstall", "")
            ("auto-start", "");

        boost::program_options::store(
            boost::program_options::parse_command_line(argc, argv, opts)
            , m_vm );

        //////////////////////////////////////////////////////////////////////////
        /// 定义SERVICE_TABLE_ENTRY DispatchTable[] 结构
        SERVICE_TABLE_ENTRYA DispatchTable[2] = 
        {
            {(char*)GetServiceName(), (LPSERVICE_MAIN_FUNCTIONA)GetServiceStartFunction()},                  
            {NULL, NULL}
        };

        if ( m_vm.count("help") )
        {
            /// 帮助
            std::cout << opts << std::endl;
        }
        else if ( m_vm.count("install") )
        {
            bool bAutoStart = (m_vm.count("auto-start") > 0);
            /// 安装服务
            if ( Install(bAutoStart) )
            {
                std::cout << "安装成功!" << std::endl;
                OnInstall(bAutoStart);
            }
            else
                std::cout << "安装失败!" << std::endl;
        }
        else if ( m_vm.count("uninstall") )
        {
            /// 卸载服务
            if ( Uninstall() )
                std::cout << "卸载成功!" << std::endl;
            else
                std::cout << "卸载失败!" << std::endl;
        }
        else
        {
            /// OS启动该程序
            BOOL bSuccessed = ::StartServiceCtrlDispatcherA(DispatchTable);
            //if (bSuccessed)
            //    LOG << "服务入口函数注册成功!" << std::endl;
            //else
            //    LOG << "服务入口函数注册失败!" << std::endl;
        }
        return 0;
    }
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        OnInitDialog(hDlg);
        return TRUE;

        
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDOK:
            EndDialog(hDlg, IDOK);
            return TRUE;

        case IDCANCEL:
            EndDialog(hDlg, IDCANCEL);
            return TRUE;

        case ID_INSTALL:
            OnInstall(hDlg);
            break;

        case ID_CONFIGURE:
            OnConfigure(hDlg);
            break;

        case ID_TEST:
            OnTest(hDlg);
            break;

        case ID_COMBO:
            if (HIWORD(wParam) == CBN_SELCHANGE)
            {
                OnTestOnWindow(hDlg);
            }
            break;
        }
        break;
    }
    return FALSE;
}
示例#5
0
void CUpgradeDialog::OnOrderbymail()
{
	// Update the product items with the selection flags from the list box.
	
	m_ProductList.UpdateProductItems();

	CInstallInfo Info;

	COrderByMailDialog Dialog(&Info, this);
	// We need to compute the various order totals so we can reflect them
	// in the order information dialog.
				
	long lTotal = 0;
	long lSubTotal = 0;
	
	TotalItems(&m_ProductList, lTotal);
	
	lSubTotal = lTotal;
	
	long lTax = m_TaxList.CurrentTax(lTotal);

	lTotal += lTax;

	long lShipping = lSubTotal > 0 ? GetApp()->Offer()->ProcessingFee() : 0;

	lTotal += lShipping;

	// Fill in values used by dialog.

	Dialog.m_lSubTotal = lSubTotal;
	Dialog.m_lTax = lTax;
	Dialog.m_lShipping = lShipping;
	Dialog.m_pOrderForm = this;
				
	if (Dialog.DoModal() == IDOK)
	{
		m_ProductList.DisableLicensedItems();
		UpdateDialog();
		OnInstall();
	}

	UpdateDialog();
}
示例#6
0
BOOL InstallerWindow::on_event(HELEMENT he, HELEMENT target, BEHAVIOR_EVENTS type, UINT_PTR reason)
{
	try
	{
		htmlayout::dom::element target_element = target;
		if (type == BUTTON_CLICK && button_skip == target_element)
		{
			OnOK();
			return TRUE;
		}
		else if (type == BUTTON_CLICK && button_cancel == target_element)
		{
			OnCancel();
			return TRUE;
		}
		else if (type == BUTTON_CLICK && (button_install == target_element || button_uninstall == target_element))
		{
			OnInstall();
			return TRUE;
		}
		else if (type == BUTTON_STATE_CHANGED || type == EDIT_VALUE_CHANGED || type == SELECT_STATE_CHANGED)
		{
			const wchar_t * component_ptr = target_element.get_attribute("component_ptr");
			if (component_ptr != NULL)
			{
				Component * p_component = reinterpret_cast<Component *>(DVLib::wstring2long(component_ptr, 16));
				p_component->checked = target_element.get_state(STATE_CHECKED);
			}
		}

		return HtmlWindow::on_event(he, target, type, reason);
	}
	catch(const std::exception& ex)
	{
		TRYLOG(L"Error: " << DVLib::string2wstring(ex.what()));
		DniMessageBox::Show(DVLib::string2wstring(ex.what()).c_str(), MB_OK|MB_ICONSTOP);
		return TRUE;
	}
}
示例#7
0
void InstallerWindow::StartInstall()
{
	OnInstall();
}
示例#8
0
void CUpgradeDialog::OnOrderbymodem()
{
	CString csReason;

	// Update the product items with the selection flags from the list box.
	m_ProductList.UpdateProductItems();
	
	if (GetApp()->Offer()->CountProductFlags(PRODUCT_ITEM_Selected) == 0)
	{
		AfxMessageBox(IDS_NO_ITEMS_SELECTED_MODEM);
		return;
	}

	// Build an CInstallInfo structure for us to use.
	CInstallInfo Info;

	// Perform the modem search.
	CSearchingDialog SearchDialog(this);

	switch (SearchDialog.DoModal())
	{
		case IDOK:
		{
			// User wants to send their order over the modem.
			int nPort = SearchDialog.m_nPort;
			long lSpeed = SearchDialog.m_lSpeed;
			BOOL fRetryRegister;
			
			int nPaymentMethod = 0;
			CString csCardNumber;
			CString csExpirationDate;

			do
			{
				fRetryRegister = FALSE;
            
				// Ask the user for some information.
				CRegistrationInformationDialog Dialog((UINT)-1, this);
				
				TRY
				{
					Dialog.m_fModemOrder = TRUE;
					Dialog.m_nPaymentMethod = nPaymentMethod;
					Dialog.m_csCardNumber = csCardNumber;
					Dialog.m_csExpirationDate = csExpirationDate;
				}
				END_TRY

				// We need to compute the various order totals so we can reflect them
				// in the order information dialog.
				
				long lTotal = 0;
				long lSubTotal = 0;
	
				TotalItems(&m_ProductList, lTotal);
	
				lSubTotal = lTotal;
	
				long lTax = m_TaxList.CurrentTax(lTotal);

				lTotal += lTax;
	
				long lShipping = lSubTotal > 0 ? Info.m_pOffer->ProcessingFee() : 0;
	
				lTotal += lShipping;

				// Fill in values used by RegInfo dialog.
				
				Dialog.m_lSubTotal = lSubTotal;
				Dialog.m_lTax = lTax;
				Dialog.m_lShipping = lShipping;
				Dialog.m_pOrderForm = this;
				
				if (Dialog.DoModal() == IDOK)
				{
					CMsregPacketHeader* pPacketHeader = NULL;
					CMsregPacketCatalogOrderRequest* pCatalogOrderData = NULL;
					CString csFileName;
					CFile cfFile;
					CString csWindowsDir;
					char* pTempName = NULL;
					BOOL fSuccess = FALSE;
					
					TRY
					{
						// Tax status may have changed, recompute some stuff.
						
						lTotal = lSubTotal;
	
						lTax = m_TaxList.CurrentTax(lTotal);

						lTotal += lTax;

						lShipping = lSubTotal > 0 ? Info.m_pOffer->ProcessingFee() : 0;

						lTotal += lShipping;
					
						nPaymentMethod = Dialog.m_nPaymentMethod;
						csCardNumber = Dialog.m_csCardNumber;
						csExpirationDate = Dialog.m_csExpirationDate;
						
						// Package the user's order into a packet.
						pCatalogOrderData = new CMsregPacketCatalogOrderRequest;

						// Product name.
						pCatalogOrderData->ProductName() = GetApp()->ApplicationName();
	
						// Product version.
						pCatalogOrderData->AddField("Version", GetApp()->MsRegIniFile().GetString(MSREGINI_Section_Configuration, MSREGINI_Configuration_Version));
	
						// Part Number.
						pCatalogOrderData->AddField("ParentPartNumber", GetApp()->MsRegIniFile().GetString(MSREGINI_Section_Configuration, MSREGINI_Configuration_ParentPartNumber));
					
						// User information.
						pCatalogOrderData->AddField("FirstName", Dialog.m_csFirstName);
						pCatalogOrderData->AddField("LastName", Dialog.m_csLastName);
						pCatalogOrderData->AddField("Company", Dialog.m_csCompany);
						pCatalogOrderData->AddField("Title", "");
						pCatalogOrderData->AddField("Address1", Dialog.m_csAddress1);
						pCatalogOrderData->AddField("Address2", Dialog.m_csAddress2);
						pCatalogOrderData->AddField("City", Dialog.m_csCity);
						pCatalogOrderData->AddField("State", Dialog.m_csState);
						pCatalogOrderData->AddField("Country", Dialog.m_csCountry);
						pCatalogOrderData->AddField("Zip", Dialog.m_csZip);
						pCatalogOrderData->AddField("Phone", Dialog.m_csPhone);
						pCatalogOrderData->AddField("Email", Dialog.m_csEmail);
						
						static char* PaymentMethodStrings[] =
						{
							"VSA",			// Visa
							"MC",				// MasterCard
							"AMX",			// American Express
							"DIS"				// Discover
						};
						
						ASSERT((Dialog.m_nPaymentMethod >= 0) && (Dialog.m_nPaymentMethod < (sizeof(PaymentMethodStrings)/sizeof(PaymentMethodStrings[0]))));
						
						if ((Dialog.m_nPaymentMethod >= 0) && (Dialog.m_nPaymentMethod < (sizeof(PaymentMethodStrings)/sizeof(PaymentMethodStrings[0]))))
						{
							pCatalogOrderData->AddField("PaymentMethod", PaymentMethodStrings[Dialog.m_nPaymentMethod]);
						}
						
						pCatalogOrderData->AddField("CardNumber", Dialog.m_csCardNumber);
						pCatalogOrderData->AddField("ExpirationDate", Dialog.m_csExpirationDate);
	
						// Tax, shipping, and total.
						pCatalogOrderData->Tax() = (DWORD)lTax;
						pCatalogOrderData->Shipping() = (DWORD)lShipping;
						pCatalogOrderData->Total() = (DWORD)lTotal;
						
						// Offer codes.
						pCatalogOrderData->OfferCode() = Info.m_pOffer->OfferCode();
						
						// Result codes.
						Info.GetLRCFromProducts(pCatalogOrderData->RequestCode());
						
						// Line Items.
						AddCatalogOrderLineItems(pCatalogOrderData, Info.m_pOffer);

						// Build packet header.					
						pPacketHeader = new CMsregPacketHeader;

						// Customer ID.
						pPacketHeader->CustomerId() = GetApp()->UserIniFile().GetString(MSREGUSRINI_Section_CustomerInfo, MSREGUSRINI_CustomerInfo_CustomerNumber);
						
						// Packet.
						pPacketHeader->AddPacket(pCatalogOrderData);
						pCatalogOrderData = NULL;
						
						// Get the Windows directory in case we need to create a
						// temporary file there.
						if (GetWindowsDirectory(csWindowsDir.GetBuffer(_MAX_PATH), _MAX_PATH) == 0)
						{
							csWindowsDir.Empty();
						}
						else
						{
							csWindowsDir.ReleaseBuffer();
						}

						// Create a temporary file name.
						pTempName = _tempnam((LPSTR)(LPCSTR)csWindowsDir, "REG");
						if (pTempName != NULL)
						{
							// Delete the file 
							csFileName = pTempName;
							free(pTempName);
							pTempName = NULL;

							if (cfFile.Open(csFileName, CFile::modeCreate|CFile::modeWrite|CFile::shareExclusive))
							{
								// Write out the packet to the temp file.
								pPacketHeader->WriteToFile(cfFile);
								fSuccess = TRUE;
							}
						}
					}
					END_TRY

					// Clean up (fSuccess indicates whether we actually had success.)
					delete pPacketHeader;
					pPacketHeader = NULL;
							
					delete pCatalogOrderData;
					pCatalogOrderData = NULL;
							
					cfFile.Close();
							
					if (pTempName != NULL)
					{
						free(pTempName);
						pTempName = NULL;
					}
					
					// If we were not successful, then it was because of some internal problem
					// such as running out of memory or not being able to create the file.
					// Put up a message and let the user try again if they want.
					
					if (!fSuccess)
					{
						AfxMessageBox(IDS_COULD_NOT_SAVE_INFORMATION);
						fRetryRegister = TRUE;
					}
					else
					{
						// Attempt to send the file to the receiver.
						CSendingDialog SendingDialog(nPort, lSpeed, csFileName, this);

						switch (SendingDialog.DoModal())
						{
							case IDOK:
							{
								// The request was successfully transmitted, we should have
								// a response. Check if the order was successfully processed.

								DWORD dwResult = CMsregPacketCatalogOrderResponse::CATALOGORDERRESULT_Error;
									
								TRY
								{
									// Attempt to open the response file.
									if (!cfFile.Open(csFileName, CFile::modeRead|CFile::shareExclusive))
									{
										AfxThrowUserException();
									}

									// Read the response packet.
									pPacketHeader = new CMsregPacketHeader;
									pPacketHeader->ReadFromFile(cfFile);

									// Validate the response.
									CMsregPacketCatalogOrderResponse* pResponse;
									if ((pPacketHeader->Type() != CMsregPacket::BLOCK_PacketHeader)
									 || (pPacketHeader->Version() != CMsregPacket::VERSION_PacketHeader)
									 || (pPacketHeader->PacketCount() != 1)
									 || ((pResponse = (CMsregPacketCatalogOrderResponse*)(pPacketHeader->GetPacket(0))) == NULL)
									 || (pResponse->Type() != CMsregPacket::BLOCK_CatalogOrderResponse)
									 || (pResponse->Version() != CMsregPacket::VERSION_CatalogOrderResponse))
									{
										AfxThrowUserException();
									}
									
									// Get the result.
									dwResult = pResponse->Result();

									// Got a response, see if the order was successful.
									if (dwResult != CMsregPacketCatalogOrderResponse::CATALOGORDERRESULT_Ok)
									{
										AfxThrowUserException();
									}

									// Remember their customer ID.
									GetApp()->UserIniFile().WriteString(MSREGUSRINI_Section_CustomerInfo, MSREGUSRINI_CustomerInfo_CustomerNumber, pPacketHeader->CustomerId());

									// Remember that they're registered.
									GetApp()->UserIniFile().WriteInteger(GetApp()->ApplicationName(), MSREGUSRINI_Application_Registered, 1);

									// "Bonus Enable" them.
									GetApp()->UserIniFile().WriteString(GetApp()->ApplicationName(), MSREGUSRINI_Application_RegistrationCode, MODEM_REGISTRATION_CODE);

									// License the products (without confirming LAC).
									Info.LicenseSelectedProducts();

									// Update the dialog to reflect the new state of the licensed products.
									CheckDlgButton(IDC_TAX_CHECK, GetApp()->UserNeedsTax());
									m_ProductList.DisableLicensedItems();
									UpdateDialog();
									
									// Let the user play with their new toys.
									OnInstall();
								}
								CATCH_ALL(e)
								{
									csReason.Empty();
								
									// Some sort of error occurred, report it.
									switch (dwResult)
									{
										case CMsregPacketCatalogOrderResponse::CATALOGORDERRESULT_InvalidCreditCardNumber:
										{
											Util::SafeLoadString(IDS_INVALID_CREDIT_CARD_NUMBER, csReason);
											break;
										}
										case CMsregPacketCatalogOrderResponse::CATALOGORDERRESULT_CreditCardExpired:
										{
											Util::SafeLoadString(IDS_EXPIRED_CREDIT_CARD, csReason);
											break;
										}
										case CMsregPacketCatalogOrderResponse::CATALOGORDERRESULT_IncompleteCustomerInformation:
										{
											Util::SafeLoadString(IDS_INCOMPLETE_CUSTOMER_INFORMATION, csReason);
											break;
										}
										default:
										{
											Util::SafeLoadString(IDS_COULD_NOT_PROCESS, csReason);
											break;
										}
									}
									
									if (!csReason.IsEmpty())
									{
										COrderFailedDialog Dialog(csReason, this);
										Dialog.DoModal();
									}
									
									// Let the user try again.
									fRetryRegister = TRUE;
								}
								END_CATCH_ALL
                        
                        // Clean up.
                        delete pPacketHeader;
                        pPacketHeader = NULL;
                        
								cfFile.Close();

								break;
							}
							case IDCANCEL:
							{
								// They want to go back. Just go back to the register dialog.
								fRetryRegister = TRUE;
								break;
							}
							case IDABORT:
							{
								// Some sort of modem error occurred, report it.
								CCallFailedDialog Dialog(this);
								Dialog.DoModal();
								fRetryRegister = TRUE;
								break;
							}
							default:
							{
								ASSERT(FALSE);
								break;
							}
						}
					}
               
               // Make sure we delete temporary file.
					TRY
					{
						CFile::Remove(csFileName);
					}
					END_TRY
				}
			} while (fRetryRegister);

			break;
		}
		case IDABORT:
		{
			// No modem was found, report this fact.
			CNoModemDialog Dialog(this);
			Dialog.DoModal();
			break;
		}
	}
   
   // Make sure the dialog is up to date.
	UpdateDialog();
}
	/** Install and Uninstall the service and write actions to the event
	log. If pszFullPath is given, it will be set as the path, otherwise the
	path will be retreived from the module name. The default command line
	processing calls this function with pszLogonAs and pszLogonPassword set
	to NULL. Override this function, and when bInstall is VTRUE, get the
	logon as and password if needed, and then call the base class function.
	pszLogonAs can be either a DomainName\UserName or just the UserName, in
	which case this function will prepend .\ which is required by the
	CreateService() API function. Returns VTRUE on success, VFALSE on
	failure.*/
	virtual VBOOL			Install(	VBOOL			bInstall =
															VTRUE,
										VDWORD			nStartType =
															SERVICE_AUTO_START,
										VSTRING_CONST	pszFullPath =
															NULL,
										VSTRING_CONST	pszLogonAs =
															NULL,
										VSTRING_CONST	pszLogonPassword =
															NULL,
										VBOOL			bStartAfterInstall =
															VTRUE,
										VBOOL			bSilentMode =
															VFALSE)
	{
		/* Service name should not be empty!*/
		VASSERT(m_strServiceName.IsNotEmpty())

		/* Assume failure.*/
		VBOOL bSuccess = VFALSE;

		/* Open the Service Control Manager.*/
		SC_HANDLE hSCM =
			OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

		if ( hSCM )
		{
			if ( bInstall )
			{
				/* Verify un-installed, first (silent mode).*/
				Install(VFALSE, 0, NULL, NULL, NULL, VFALSE, VTRUE);

				/* Get this executables file path (unless given
				in pszFullPath).*/
				VString sPath;

				if ( !pszFullPath )
					sPath.GetModulePath(VFALSE, VFALSE);
				else
					sPath = pszFullPath;

				if ( sPath.IsNotEmpty() )
				{
					/* If pszLogonAs is not NULL, verify domain name is
					present, and if not, .\ is present. If neither is the
					case, we will modify the logon as to be correct.*/
					VString strLogonAs;

					if ( pszLogonAs )
					{
						/* If we find a \ assume correct DomainName\UserName
						string.*/
						if ( !VSTRCHR(pszLogonAs, VTEXT('\\')) )
						{
							/* Domain Name not given, so does the
							string already contain .\ sequence as the
							first chars?*/
							if (	!(*pszLogonAs == VTEXT('.') &&
									*(pszLogonAs + 1) == VTEXT('\\')) )
							{
								strLogonAs = VTEXT(".\\");
								strLogonAs += pszLogonAs;
								pszLogonAs = strLogonAs;
							}
						}
					}

					/* We want no error condition now.*/
					SetLastError(0);

					/* Create the service.*/
					SC_HANDLE hService =
						CreateService(	hSCM,
										m_strServiceName,
										m_strServiceName,
										SERVICE_ALL_ACCESS,
										m_Status.dwServiceType,
										nStartType,
										SERVICE_ERROR_NORMAL,
										sPath,
										NULL,
										NULL,
										NULL,
										pszLogonAs,
										pszLogonPassword);

					if (	hService ||
							GetLastError() == ERROR_SERVICE_EXISTS )
					{
						/* Make or verify registry entries to
						support event logging.*/
						bSuccess =
							(m_hEventSource)
							? VTRUE
							: Register(m_strServiceName);

						if (	hService &&
								bSuccess &&
								bStartAfterInstall )
						{
							bSuccess =
								StartService(hService, 0, NULL);

							/* If service fails to start now, un-install it.*/
							if ( !bSuccess )
							{
								/* Close handle first.*/
								CloseServiceHandle(hService);
								hService = NULL;

								/* Un-Install in silent mode.*/
								Install(	VFALSE,
											0,
											NULL,
											NULL,
											NULL,
											VFALSE,
											VTRUE);
							}
						}

						if ( hService )
							CloseServiceHandle(hService);
					}
				}

				/* Log what happened if we can.*/
				LogEvent(	(bSuccess)
							? EM_SERVICE_INSTALLED
							: EM_SERVICE_NOT_INSTALLED,
							(bSuccess)
							? VFALSE
							: VTRUE);

				/* Notify via virtual function.*/
				OnInstall(bSuccess, bSilentMode);
			}
			else
			{
				SC_HANDLE hService =
					OpenService(	hSCM,
									m_strServiceName,
									SERVICE_QUERY_STATUS | DELETE);

				if ( hService )
				{
					/* If the service is running, stop it.*/
					SERVICE_STATUS ss;

					if ( QueryServiceStatus(hService, &ss) )
					{
						if ( ss.dwCurrentState != SERVICE_STOPPED )
						{
							/* Get a handle we can use to
							stop the service.*/
							SC_HANDLE hStopService =
								OpenService(	hSCM,
												m_strServiceName,
												SERVICE_STOP);

							if ( hStopService )
							{
								SERVICE_STATUS ss;
								ControlService(	hStopService,
												SERVICE_CONTROL_STOP, &ss);

								CloseServiceHandle(hStopService);
							}
						}
					}

					bSuccess =
						(hService && DeleteService(hService))
						? VTRUE
						: VFALSE;

					CloseServiceHandle(hService);
				}
				else
					bSuccess = VTRUE;

				/* Remove registry entries on success.*/
				if ( bSuccess )
				{
					VRegistry reg;

					if ( reg.CreateKey(GetRegistryKey(), HKEY_LOCAL_MACHINE) )
						reg.DeleteSubKeyNT(m_strServiceName);
				}

				/* Log what happened if we can.*/
				LogEvent(	(bSuccess)
							? EM_SERVICE_UNINSTALLED
							: EM_SERVICE_NOT_REMOVED,
							(bSuccess)
							? VFALSE
							: VTRUE);

				/* Notify via virtual function.*/
				OnUnInstall(bSuccess, bSilentMode);
			}

			CloseServiceHandle(hSCM);
		}

		return bSuccess;
	}