bool SetPreference ( WStringAutoPtr key, WStringAutoPtr value, WStringAutoPtr domain )
{
    HKEY registry_key;

    LSTATUS status;

    status = RegCreateKeyEx ( HKEY_CURRENT_USER,
                              domain->c_str(),
                              0,
                              NULL,
                              REG_OPTION_NON_VOLATILE,
                              KEY_WRITE,
                              NULL,
                              &registry_key,
                              NULL
                            );

    if ( status == ERROR_SUCCESS ) {

        status = RegSetValueEx ( registry_key,
                                 key->c_str(),
                                 0,
                                 REG_SZ,
                                 (PBYTE)value->c_str(),
                                 (DWORD)(value->size() * sizeof(wchar_t)) + 1
                               );
        RegCloseKey ( registry_key );
    }

    g_last_error = (fmx::errcode)status;

    return ( status == ERROR_SUCCESS );

}
WStringAutoPtr SelectFile ( WStringAutoPtr prompt, WStringAutoPtr in_folder )
{
	OPENFILENAME open_file_dialog;   // common dialog box structure

	ZeroMemory ( &open_file_dialog, sizeof(open_file_dialog) );

	open_file_dialog.lStructSize = sizeof(open_file_dialog);
	open_file_dialog.hwndOwner = GetActiveWindow();

	wchar_t szFile[MAX_PATH];        // buffer for file name
	open_file_dialog.lpstrFile = szFile;
	open_file_dialog.lpstrFilter = L"All Files (*.*)\0*.*\0";
	open_file_dialog.lpstrFile[0] = '\0';
	open_file_dialog.nMaxFile = sizeof(szFile);
	open_file_dialog.lpstrTitle = prompt->c_str();
	open_file_dialog.lpstrInitialDir = in_folder->c_str();
	open_file_dialog.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;

	 // Display the Open dialog box

	wchar_t path[MAX_PATH] = L"";

	if ( GetOpenFileName ( &open_file_dialog ) == TRUE ) {
		wcscpy_s ( path, open_file_dialog.lpstrFile );
	 }

	 return WStringAutoPtr ( new wstring ( path ) );

}	//	SelectFile
WStringAutoPtr GetPreference ( WStringAutoPtr key, WStringAutoPtr domain )
{

    HKEY registry_key;
    DWORD buffer_size = 1024;
    wchar_t * preference_data = new wchar_t[buffer_size]();

    LSTATUS status;

    status = RegOpenKeyEx ( HKEY_CURRENT_USER,
                            domain->c_str(),
                            NULL,
                            KEY_READ,
                            &registry_key
                          );

    if ( status == ERROR_SUCCESS ) {

        status = RegQueryValueEx ( registry_key,
                                   key->c_str(),
                                   NULL,
                                   NULL,
                                   (LPBYTE)preference_data,
                                   &buffer_size
                                 );

        // if preference_data isn't big enough resize it and try again
        if ( status == ERROR_MORE_DATA ) {

            delete [] preference_data;
            preference_data = new wchar_t[buffer_size + 1]();

            status = RegQueryValueEx ( registry_key,
                                       key->c_str(),
                                       NULL,
                                       NULL,
                                       (LPBYTE)preference_data,
                                       &buffer_size
                                     );
        }
        RegCloseKey ( registry_key );
    }

    WStringAutoPtr value = WStringAutoPtr ( new wstring ( preference_data ) );

    delete [] preference_data;

    g_last_error = (fmx::errcode)status;

    return value;

}
fmx::errcode UpdateProgressDialog ( const unsigned long value, const WStringAutoPtr description )
{
    fmx::errcode error = kNoError;

    BOOL user_cancelled = progress_dialog->HasUserCancelled();

    if ( (user_cancelled != 0) || (value > progress_dialog_maximum) ) {

        progress_dialog->StopProgressDialog();
        progress_dialog->Release();
        progress_dialog = NULL;

        error = user_cancelled ? kUserCancelledError : error;

    } else {

        HRESULT result;

        if ( !description->empty () ) {
            result = progress_dialog->SetLine ( 2, description->c_str (), false, NULL );
        }

        if ( result == S_OK ) {
            result = progress_dialog->SetProgress ( value, progress_dialog_maximum );
            error = result == S_FALSE ? kNoError : (fmx::errcode)result;
        }
    }

    return error;
}
fmx::errcode UpdateProgressDialog ( const long value, const WStringAutoPtr description )
{
	fmx::errcode error = kNoError;

	bool user_cancelled = progress_dialog->HasUserCancelled();

	if ( user_cancelled || value > progress_dialog_maximum ) {

		progress_dialog->StopProgressDialog();
		progress_dialog->Release();
        progress_dialog = NULL;

		error = user_cancelled ? kUserCancelledError : error;

	} else {

		if ( !description->empty () ) {
			error = progress_dialog->SetLine ( 2, description->c_str (), false, NULL );
		}

		if ( error == S_OK ) {
			error = progress_dialog->SetProgress ( value, progress_dialog_maximum );
			error = error == S_FALSE ? kNoError : error;
		}
	}

	return error;
}
int DisplayDialog ( WStringAutoPtr title, WStringAutoPtr message, WStringAutoPtr button1, WStringAutoPtr button2, WStringAutoPtr button3 )
{
    // set the names to be used for each button
    g_button1_name.swap ( *button1 );
    g_button2_name.swap ( *button2 );
    g_button3_name.swap ( *button3 );

    // the type of dialog displayed varies depends on the nunmber of buttons required
    UINT type = MB_OK;

    if ( g_button2_name != L"" ) {
        type = MB_OKCANCEL;
        if ( g_button3_name != L"" ) {
            type = MB_YESNOCANCEL;
        }
    }

    // set the callback so that the custom button names are installed
    g_window_hook = SetWindowsHookEx ( WH_CBT, &DialogCallback, 0, GetCurrentThreadId() );

    /*
     get the user's choice and translate that into a response that matches the equivalent
     choice on OS X
     */

    int button_clicked = MessageBox ( GetForegroundWindow(), message->c_str(), title->c_str(), type );

    unsigned long response = 0;

    switch ( button_clicked ) {

    case IDOK:
    case IDYES:
        response = kBE_OKButton;
        break;
    case IDCANCEL:
        response = kBE_CancelButton;
        break;
    case IDNO:
        response = kBE_AlternateButton;
        break;
    }

    return response;

} // DisplayDialog
bool OpenURL ( WStringAutoPtr url )
{

    HINSTANCE result = ShellExecute ( NULL, (LPCWSTR)L"open", url->c_str(), NULL, NULL, SW_SHOWNORMAL );

    // see http://msdn.microsoft.com/en-us/library/bb762153(VS.85).aspx

    return ( result > (HINSTANCE)32 );
}
fmx::errcode DisplayProgressDialog ( const WStringAutoPtr title, const WStringAutoPtr description, const long maximum, const bool can_cancel )
{
	HRESULT result = S_OK;

	if ( progress_dialog ) {
		result = kFileOrObjectIsInUse;
	} else {

		progress_dialog_maximum = maximum;

		HWND parent_window = GetForegroundWindow();
		result = CoCreateInstance ( CLSID_ProgressDialog, NULL, CLSCTX_INPROC_SERVER, IID_IProgressDialog, (void**)&progress_dialog );

		if ( result == S_OK ) {
			result = progress_dialog->SetTitle ( title->c_str () );
		}

		if ( result == S_OK ) {
			result = progress_dialog->SetLine ( 2, description->c_str (), false, NULL );
		}

		DWORD flags = PROGDLG_NORMAL;
		if ( !can_cancel ) {
			flags |= PROGDLG_NOCANCEL;
		}

		if ( 0 == maximum ) {
			flags |= PROGDLG_MARQUEEPROGRESS;
		}

		if ( result == S_OK ) {
			result = progress_dialog->StartProgressDialog ( parent_window, NULL, flags, NULL );
		}

	}

	return (fmx::errcode)result;

} // DisplayProgressDialog
fmx::errcode DisplayProgressDialog ( const WStringAutoPtr title, const WStringAutoPtr description, const long maximum, const bool can_cancel )
{
	fmx::errcode error = kNoError;

	if ( progress_dialog ) {
		return error;
	}

	progress_dialog_maximum = maximum;

	HWND parent_window = GetActiveWindow ( );
	error = CoCreateInstance ( CLSID_ProgressDialog, NULL, CLSCTX_INPROC_SERVER, IID_IProgressDialog, (void**)&progress_dialog );

	if ( error == S_OK ) {
		error = progress_dialog->SetTitle ( title->c_str () );
	}

	if ( error == S_OK ) {
		progress_dialog->SetLine ( 2, description->c_str (), false, NULL );
	}

	DWORD flags = PROGDLG_NORMAL;
	if ( !can_cancel ) {
		flags |= PROGDLG_NOCANCEL;
	}

	if ( 0 == maximum ) {
		flags |= PROGDLG_MARQUEEPROGRESS;
	}

	if ( error == S_OK ) {
		error = progress_dialog->StartProgressDialog ( parent_window, NULL, flags, NULL );
	}

	return error;

} // DisplayProgressDialog
WStringAutoPtr SelectFolder ( WStringAutoPtr prompt, WStringAutoPtr in_folder )
{
    BROWSEINFO browse_info = { 0 };
    browse_info.hwndOwner = GetActiveWindow();
    browse_info.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
    browse_info.lpszTitle = prompt->c_str();
    if ( !in_folder->empty() ) {
        browse_info.lpfn = SelectFolderCallback;
        browse_info.lParam = (LPARAM)in_folder->c_str();
    }

    LPITEMIDLIST item_list = SHBrowseForFolder ( &browse_info );

    // if the user hasn't cancelled the dialog get the path to the folder

    wchar_t path[MAX_PATH] = L"";

    if ( item_list != 0 ) {
        SHGetPathFromIDList ( item_list, path );
    }

    return WStringAutoPtr ( new wstring ( path ) );

}	//	SelectFolder
WStringAutoPtr SelectFile ( WStringAutoPtr prompt )
{
	CWnd * parent_window = CWnd::FromHandle ( GetActiveWindow() );
	CString filter =  "All Files (*.*)|*.*||";
	CFileDialog file_dialog ( TRUE, NULL, NULL, OFN_HIDEREADONLY, filter, parent_window, 0 );
	file_dialog.m_ofn.lpstrTitle = prompt->c_str();

	// if the user hasn't cancelled the dialog get the path to the file

	wchar_t path[MAX_PATH] = L"";
	
	if ( file_dialog.DoModal() == IDOK ) {
		CString file_path = file_dialog.GetPathName();
		wcscpy_s ( path, (LPCTSTR)file_path );
	}

	return WStringAutoPtr ( new wstring ( path ) );

}	//	SelectFile
WStringAutoPtr SelectFolder ( WStringAutoPtr prompt )
{
	BROWSEINFO browse_info = { 0 };
	browse_info.hwndOwner = GetActiveWindow();
	browse_info.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI | BIF_NONEWFOLDERBUTTON;
    browse_info.lpszTitle = prompt->c_str();

    LPITEMIDLIST item_list = SHBrowseForFolder ( &browse_info );
	
	// if the user hasn't cancelled the dialog get the path to the folder

    wchar_t path[MAX_PATH] = L"";

	if ( item_list != 0 ) {
		SHGetPathFromIDList ( item_list, path );
	}

	return WStringAutoPtr ( new wstring ( path ) );

}	//	SelectFolder
StringAutoPtr ClipboardData ( WStringAutoPtr atype )
{
	char * clipboard_data = NULL;

	if ( OpenClipboard ( NULL ) ) {
		
		UINT format_wanted = RegisterClipboardFormat ( atype->c_str() );

		if ( IsClipboardFormatAvailable ( format_wanted ) ) {
			
			HGLOBAL memory_handle = GetClipboardData ( format_wanted );
			unsigned char * clipboard_contents = (unsigned char *)GlobalLock ( memory_handle );
			UINT clipboard_size = GlobalSize ( memory_handle );

			clipboard_data = new char [ clipboard_size + 1 ]();
			memcpy ( clipboard_data, clipboard_contents, clipboard_size );

			GlobalUnlock ( memory_handle );

		}
		
		CloseClipboard();
	
	} 
	
	if ( !clipboard_data ) {
		clipboard_data = new char [ 1 ]();
	}

	/* 
	 prefix the data to place on the clipboard with the size of the data
	 */
	UINT32 offset = ClipboardOffset ( *atype );
	StringAutoPtr reply ( new string ( clipboard_data + offset ) );

	delete[] clipboard_data;

	return reply;

} // ClipboardData
errcode TextConstantFunction ( WStringAutoPtr text, Data& results )
{
	
	errcode error_result = kNoError;
	
	try {
		
		TextAutoPtr result_text;
		result_text->AssignWide ( text->c_str() );
		
		LocaleAutoPtr default_locale;
		results.SetAsText ( *result_text, *default_locale );
		
	} catch ( bad_alloc& e ) {
		error_result = kLowMemoryError;
	} catch ( exception& e ) {
		error_result = kErrorUnknown;
	}
	
	return error_result;
	
} // TextConstantFunction
bool SetClipboardData ( StringAutoPtr data, WStringAutoPtr atype )
{
	bool ok = FALSE;
	
	if ( OpenClipboard ( NULL ) ) {
		
		EmptyClipboard();

		SIZE_T data_size = data->size();

		/* 
		 prefix the data to place on the clipboard with the size of the data
		 */
		SIZE_T offset = ClipboardOffset ( *atype );
		SIZE_T clipboard_size = data_size + offset;
		HGLOBAL memory_handle = GlobalAlloc ( GMEM_SHARE | GMEM_MOVEABLE, clipboard_size );

		unsigned char * clipboard_contents = (unsigned char *)GlobalLock ( memory_handle );
		if ( IsFileMakerClipboardType ( *atype ) == TRUE ) {
			memcpy ( clipboard_contents, &data_size, offset );
		}
		memcpy ( clipboard_contents + offset, data->c_str(), clipboard_size );

		GlobalUnlock ( memory_handle );

		UINT format = RegisterClipboardFormat ( atype->c_str() );
		
		if ( SetClipboardData ( format, clipboard_contents ) ) {
			ok = TRUE;
		}

		CloseClipboard();

	}

	return ok;

}	//	Set_ClipboardData
void SetResult ( const WStringAutoPtr text, Data& results )
{
	TextAutoPtr result_text;
	result_text->AssignWide ( text->c_str() );			
	SetResult ( *result_text, results );
}