Ubuntu: Getting nasty to restore Wubi Boot loader

 

This post is about restoring the boot loader for the Ubuntu Linux which is installed under Windows using WUBI installer. DO THIS AT YOUR OWN RISK. NOTE THAT NO SCREENSHOTS AVAILABLE. READ CAREFULLY BEFORE TRYING. POST A COMMENT OF YOU’RE STUCK OR FACING SOME ISSUES.

The Advice

Always backup at least a single copy of your disks folder under your Ubuntu installation beacause some of the updates sometimes make the system crash or make unstable. Especially I face several issues after changing to Gnome 3 theme.

The Problem

If Windows 7 detects any issues with the boot sector, it will automatically start boot repair (Spawns the installer screen to repair the boot). There’s a high chance to tamper the boot record in case if we cancel in between or even the Windows restore the boot sector (You may get improper entry to Ubuntu Linux or it may even removed from the screen). Your Windows will boot fine but Ubuntu. See the following error I faced while booting to Ubuntu.

Error: cannot find GRLDR in all drive. CTRL+ALT+DEL to restart.

Easy Re-installation

Don’t touch your boot record. You can simply take backup of the disks folder under the Ubuntu installation (or full backup) and go for re-installation. Uninstall Ubuntu and install it again. Now replace the disks folder in the new installation with the backed-up disk folder. Done! Reboot your machine. But there’s a high chance to get failed with this procedure if the boot sector is already tampered. The Installer may show error about invalid boot entry and failed to uninstall. In such cases we’ve to get our hands dirty!

Dirty Hands

This is quite straightforward and nasty. Take care!

Pre-Requisites

Restoring Boot Record

I tried to recreate the boot entry using EasyBCD, an amazing and reliable tool to manage the bootloader. But EasyBCD can’t solve the problem with WUBI boot loader. It will just create a raw entry in the boot sector and manually required to edit it using bcdedit. (start BCDEdit from elevated command prompt). How to geek has explained the tips to restore the boot loader in detail. But it didn’t work for me, same error occurred after rebooting

The issues gonna face after repairing boot entry

The first work around we can try is restoring the boot sector with EasyBCD. If this works fine, then nothing proceed.
If the tip mentioned in ‘How To Geek’ doesn’t work, then you have to get really nasty. Uninstalling Ubuntu will look for a proper boot record which was originally created by Ubuntu Windows Installer. It may show error as we manually modified the boot entry. The uninstallation may fail.

How to get rid of Un-Installation and Re-Install Ubuntu?

As it’s impossible to uninstall, we’ve to manually delete the Ubuntu installation entry from the Windows registry. Otherwise Ubuntu installer for Windows will not allow you to install it again.

NOTE: Take backup of your Ubuntu installation folder before proceeding.

  1. Delete the boot entry using EasyBCD or BCD edit.
  2. Delete the Ubuntu entry from installed program list using tools like CCleaner (Tools->Select Ubuntu->Delete Entry. NOTE: don’t uninstall it)
  3. Now neither your system nor the Ubuntu installer knows that Ubuntu exists in your disk
  4. Just proceed with ‘Install under Windows’
  5. Now replace the Disks folder in your newly installed location with the disks folder in the previous (backed up) installtion.
  6. Now reboot.

Done!

 

Why I can’t set cursor position on a child control during OnInitDialog?

 

One of my colleague asked me. “Why I can’t set the cursor position on a button during OnInitDialog? I need to set the cursor over a button inside the dialog during startup.” The snippet looks like below

BOOL CCursorPositionDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CRect rect;
	GetDlgItem( IDC_BUTTON2 )->GetWindowRect( rect );
	SetCursorPos(rect.left, rect.top );
}

The reason is, the Window initialization has not completed during OnInitDialog operation (even window is not displayed). Once after OnInitDialog returns, the dialog will be positioned, the input focus will be set the child control and finally the dialog is displayed. Also if you notice the, GetWindowRect returns incorrect window cordinate during OnInitDialog execution.

To solve this issue, it’s necessary to rely on other activation functions like WM_ACTIVATE or WM_WINDOWPOSCHANGED (only once) function

void CCursorPositionDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
	CDialog::OnActivate(nState, pWndOther, bMinimized);

	if( WA_ACTIVE == nState )
		SetMousePosition();
}

Alternate method (not recommended)

void CCursorPositionDlg::OnWindowPosChanged(WINDOWPOS* lpwndpos)
{
	CDialog::OnWindowPosChanged(lpwndpos);

 	static bool bFirst = true;
 	if( bFirst) { PositionButton(); bFirst = false;}
}
 

How to get known folder path (Windows Vista/7)?

 
Windows Vista and above supports independent software vendors (ISV) to add support for custom known folder locations. Previously a fixed set of IDs were provided to use with SHGetFolderPath, SHGetFolderLocation and SHSetFolderPath APIs.
For adding this flexibility, the known file APIs has been rename and designed with COM Interfaces.
New Shell APIs and COM Interfaces are introduced to replace the old Shell APIs

New Function Replaces COM Equivalent
SHGetKnownFolderPath SHGetFolderPath IKnownFolder::GetPath
SHGetKnownFolderIDList SHGetFolderLocation IKnownFolder::GetIDList
SHSetKnownFolderPath SHSetFolderPath IKnownFolder::SetPath

Old APIs were using CSIDL for representing the known location identifier. This has been replaced by KNOWFOLDERID. However Windows Vista and 7 still supports CSIDL and associated APIs for compatibility reasons. The new applications has to use the new APIs or COM Interface. When using both COM/New Shell API, you’ve to ensure that CoTaskMemFree function is called to release the output resources. Otherwise memory leak may occur. Also don’t call any other memory release function like free or delete operator. It may cause undefined behavior

How to Enumerate All Known Folders?

void EnumerateAllKnownFolders(CStringArray& strArray)
{
	CStringArray strPathRet;
	IKnownFolderManager* pkfm = NULL;
	HRESULT hr = CoCreateInstance(CLSID_KnownFolderManager, NULL,
		CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pkfm));

	if( SUCCEEDED(hr))
	{
		KNOWNFOLDERID* rfid;
		UINT uCount = 0;

		if( FAILED( pkfm->GetFolderIds( &rfid, &uCount )))
			return;

		for (UINT uIdx = 0; uIdx < uCount; ++uIdx )
		{
			IKnownFolder* pFolder;
			pkfm->GetFolder( rfid[uIdx], &pFolder );
			LPWSTR szPath;
			pFolder->GetPath(0, &szPath );
			strArray.Add( szPath );
			CoTaskMemFree( szPath );
			pFolder->Release();
		}

		CoTaskMemFree( rfid );
		pkfm->Release();
	}
}

How to get the path of a specific known folder using new COM Interface?

CString GetKnownFolderIDCOM( KNOWNFOLDERID rfid )
{
	CString strPathRet;
	LPWSTR szPath;
	IKnownFolderManager* pkfm = NULL;
	HRESULT hr = CoCreateInstance(CLSID_KnownFolderManager, NULL,
		CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pkfm));

	if( SUCCEEDED(hr))
	{
		IKnownFolder* pFolder;
		pkfm->GetFolder( rfid, &pFolder );

		pFolder->GetPath(0, &szPath );
		strPathRet = szPath;
		CoTaskMemFree( szPath );
		pFolder->Release();
	}
	pkfm->Release();
	return strPathRet;
}

How to get path of a specific known folder Shell API?

CString GetKnownPathShell( KNOWNFOLDERID rfid )
{
	CString strPath;
	LPWSTR szPath;
	SHGetKnownFolderPath( rfid, 0, 0, &szPath );
	strPath = szPath;
	CoTaskMemFree( szPath );
	return strPath;
}
 

Proudly powered by WordPress
Theme: Esquire by Matthew Buchanan.