/*******************************************************************************
 * Copyright (c) 2010, 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Tasktop Technologies - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.widgets;


import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.*;

/**
 * Instances of this class represent the system task bar.
 * 
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>(none)</dd>
 * <dt><b>Events:</b></dt>
 * <dd>(none)</dd>
 * </dl>
 * 
 * @see Display#getSystemTaskBar
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 * 
 * @since 3.6
 * 
 * @noextend This class is not intended to be subclassed by clients.
 */
public class TaskBar extends Widget {
	int itemCount;
	TaskItem [] items = new TaskItem [4];
	long /*int*/ mTaskbarList3;
	
	static final char [] EXE_PATH;
	static final char [] ICO_DIR = {'i','c','o','_','d','i','r','\0'};
	static final PROPERTYKEY PKEY_Title = new PROPERTYKEY ();
	static final PROPERTYKEY PKEY_AppUserModel_IsDestListSeparator = new PROPERTYKEY ();
	static final String EXE_PATH_KEY = "org.eclipse.swt.win32.taskbar.executable";  //$NON-NLS-1$
	static final String EXE_ARGS_KEY = "org.eclipse.swt.win32.taskbar.arguments";  //$NON-NLS-1$
	static final String ICON_KEY = "org.eclipse.swt.win32.taskbar.icon";  //$NON-NLS-1$
	static final String ICON_INDEX_KEY = "org.eclipse.swt.win32.taskbar.icon.index";  //$NON-NLS-1$
	static final byte [] CLSID_TaskbarList = new byte [16]; 
	static final byte [] CLSID_DestinationList = new byte[16]; 
	static final byte [] CLSID_EnumerableObjectCollection = new byte[16]; 
	static final byte [] CLSID_ShellLink = new byte[16]; 
	static final byte [] CLSID_FileOperation = new byte [16];
	static final byte [] IID_ITaskbarList3 = new byte [16];
	static final byte [] IID_ICustomDestinationList = new byte[16]; 
	static final byte [] IID_IObjectArray = new byte[16]; 
	static final byte [] IID_IObjectCollection = new byte[16]; 
	static final byte [] IID_IShellLinkW = new byte[16]; 
	static final byte [] IID_IPropertyStore = new byte[16]; 
	static final byte [] IID_IShellItem = new byte [16]; 
	static final byte [] IID_IFileOperation = new byte [16];
	static final byte [] FOLDERID_LocalAppData = new byte [16];
	static {
		OS.IIDFromString ("{56FDF344-FD6D-11d0-958A-006097C9A090}\0".toCharArray (), CLSID_TaskbarList); //$NON-NLS-1$
		OS.IIDFromString ("{77f10cf0-3db5-4966-b520-b7c54fd35ed6}\0".toCharArray (), CLSID_DestinationList); //$NON-NLS-1$
		OS.IIDFromString ("{2d3468c1-36a7-43b6-ac24-d3f02fd9607a}\0".toCharArray (), CLSID_EnumerableObjectCollection); //$NON-NLS-1$
		OS.IIDFromString ("{00021401-0000-0000-C000-000000000046}\0".toCharArray (), CLSID_ShellLink); //$NON-NLS-1$
		OS.IIDFromString ("{3ad05575-8857-4850-9277-11b85bdb8e09}\0".toCharArray (), CLSID_FileOperation);
		OS.IIDFromString ("{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}\0".toCharArray (), IID_ITaskbarList3); //$NON-NLS-1$	
		OS.IIDFromString ("{6332debf-87b5-4670-90c0-5e57b408a49e}\0".toCharArray (), IID_ICustomDestinationList); //$NON-NLS-1$
		OS.IIDFromString ("{92CA9DCD-5622-4bba-A805-5E9F541BD8C9}\0".toCharArray (), IID_IObjectArray); //$NON-NLS-1$
		OS.IIDFromString ("{5632b1a4-e38a-400a-928a-d4cd63230295}\0".toCharArray (), IID_IObjectCollection); //$NON-NLS-1$
		OS.IIDFromString ("{000214F9-0000-0000-C000-000000000046}\0".toCharArray (), IID_IShellLinkW); //$NON-NLS-1$
		OS.IIDFromString ("{886d8eeb-8cf2-4446-8d02-cdba1dbdcf99}\0".toCharArray (), IID_IPropertyStore); //$NON-NLS-1$
		OS.IIDFromString ("{43826d1e-e718-42ee-bc55-a1e261c37bfe}\0".toCharArray (), IID_IShellItem); //$NON-NLS-1$
		OS.IIDFromString ("{947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8}\0".toCharArray (), IID_IFileOperation); //$NON-NLS-1$
		OS.IIDFromString ("{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}\0".toCharArray (), FOLDERID_LocalAppData); //$NON-NLS-1$
		OS.PSPropertyKeyFromString ("{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 2\0".toCharArray (), PKEY_Title); //$NON-NLS-1$
		OS.PSPropertyKeyFromString ("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 6\0".toCharArray (), PKEY_AppUserModel_IsDestListSeparator); //$NON-NLS-1$
		TCHAR buffer = new TCHAR (0, OS.MAX_PATH);
		while (OS.GetModuleFileName (0, buffer, buffer.length ()) == buffer.length ()) {
			buffer = new TCHAR (0, buffer.length () + OS.MAX_PATH);
		}
		int length = buffer.strlen ();
		EXE_PATH = new char [length + 1];
		System.arraycopy (buffer.chars, 0, EXE_PATH, 0, length);
	}

TaskBar (Display display, int style) {
	if (display == null) display = Display.getCurrent ();
	if (display == null) display = Display.getDefault ();
	if (!display.isValidThread ()) {
		error (SWT.ERROR_THREAD_INVALID_ACCESS);
	}
	this.display = display;
	createHandle ();
	reskinWidget ();
}

void createHandle () {
	long /*int*/[] ppv = new long /*int*/ [1];
	int hr = OS.CoCreateInstance (CLSID_TaskbarList, 0, OS.CLSCTX_INPROC_SERVER, IID_ITaskbarList3, ppv);
	if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
	mTaskbarList3 = ppv [0];
}

void createItem (TaskItem item, int index) {
	if (index == -1) index = itemCount;
	if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE);
	if (itemCount == items.length) {
		TaskItem [] newItems = new TaskItem [items.length + 4];
		System.arraycopy (items, 0, newItems, 0, items.length);
		items = newItems;
	}
	System.arraycopy (items, index, items, index + 1, itemCount++ - index);
	items [index] = item;
}

void createItems () {
	Shell [] shells = display.getShells ();
	for (int i = 0; i < shells.length; i++) {
		getItem (shells[i]);
	}
	getItem (null);
}

long /*int*/ createShellLink (MenuItem item, String directory) {
	int style = item.getStyle ();
	if ((style & SWT.CASCADE) != 0) return 0;
	long /*int*/ [] ppv = new long /*int*/ [1];
	int hr = OS.CoCreateInstance (CLSID_ShellLink, 0, OS.CLSCTX_INPROC_SERVER, IID_IShellLinkW, ppv);
	if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
	long /*int*/ pLink = ppv [0];

	long /*int*/ hHeap = OS.GetProcessHeap ();
	long /*int*/ pv = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, OS.PROPVARIANT_sizeof());
	long /*int*/ titlePtr = 0;
	PROPERTYKEY key;
	if ((style & SWT.SEPARATOR) != 0) {
		OS.MoveMemory (pv, new short [] {OS.VT_BOOL}, 2);
		OS.MoveMemory (pv + 8, new short [] {OS.VARIANT_TRUE}, 2);
		key = PKEY_AppUserModel_IsDestListSeparator;
	} else {
		String text = item.getText ();
		int length = text.length ();
		char [] buffer = new char [length + 1];
		text.getChars (0, length, buffer, 0);
		titlePtr = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, buffer.length * 2);
		OS.MoveMemory (titlePtr, buffer, buffer.length * 2);
		OS.MoveMemory (pv, new short [] {OS.VT_LPWSTR}, 2);
		OS.MoveMemory (pv + 8, new long /*int*/ [] {titlePtr}, OS.PTR_SIZEOF);
		key = PKEY_Title;
		
		/*IShellLink::SetPath*/
		String exePath = (String)item.getData (EXE_PATH_KEY);
		if (exePath != null) {
			length = exePath.length ();
			buffer = new char [length + 1];
			exePath.getChars (0, length, buffer, 0);
		} else {
			buffer = EXE_PATH;
		}
		hr = OS.VtblCall (20, pLink, buffer);
		if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
		
		text =  (String)item.getData (EXE_ARGS_KEY);
		if (text == null) text = Display.LAUNCHER_PREFIX + Display.TASKBAR_EVENT + item.id;
		length = text.length ();
		buffer = new char [length + 1];
		text.getChars (0, length, buffer, 0);
		/*IShellLink::SetArguments*/
		hr = OS.VtblCall (11, pLink, buffer);
		if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
		
		/* This code is intentionally commented */
//		String tooltip = item.tooltip;
//		if (tooltip != null) {
//			length = tooltip.length ();
//			buffer = new char [length + 1];
//			tooltip.getChars (0, length, buffer, 0);
//			/*IShellLink::SetDescription*/
//			hr = OS.VtblCall (7, pLink, buffer);
//			if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
//		}
		
		String icon = (String)item.getData (ICON_KEY);
		int index = 0;
		if (icon != null) {
			text = (String)item.getData (ICON_INDEX_KEY);
			if (text != null) index = Integer.parseInt (text);
		} else {
			Image image = item.getImage ();
			if (image != null && directory != null) {
				icon = directory + "\\menu" + item.id + ".ico" ;
				ImageData data;
				if (item.hBitmap != 0) {
					Image image2 = Image.win32_new (display, SWT.BITMAP, item.hBitmap);
					data = image2.getImageData ();
				} else {
					data = image.getImageData ();
				}
				ImageLoader loader = new ImageLoader ();
				loader.data = new ImageData [] {data};
				loader.save (icon, SWT.IMAGE_ICO);
			}
		}
		if (icon != null) {
			length = icon.length ();
			buffer = new char [length + 1];
			icon.getChars (0, length, buffer, 0);
			/*IShellLink::SetIconLocation*/
			hr = OS.VtblCall (17, pLink, buffer, index);
			if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
		}
	}
	
	/*IUnknown::QueryInterface*/
	hr = OS.VtblCall (0, pLink, IID_IPropertyStore, ppv);
	if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
	long /*int*/ pPropStore = ppv [0];
	/*IPropertyStore::SetValue*/
	hr = OS.VtblCall (6, pPropStore, key, pv);
	if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
	/*IPropertyStore::Commit*/
	OS.VtblCall (7, pPropStore);
	/*IUnknown::Release*/
	OS.VtblCall (2, pPropStore);
	
	OS.HeapFree (hHeap, 0, pv);
	if (titlePtr != 0) OS.HeapFree (hHeap, 0, titlePtr);
	return pLink;
}

long /*int*/ createShellLinkArray (MenuItem [] items, String directory) {
	if (items == null) return 0;
	if (items.length == 0) return 0;
	long /*int*/ [] ppv = new long /*int*/ [1];
	int hr = OS.CoCreateInstance (CLSID_EnumerableObjectCollection, 0, OS.CLSCTX_INPROC_SERVER, IID_IObjectCollection, ppv);
	if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
	long /*int*/ pObjColl = ppv [0];
	for (int i = 0; i < items.length; i++) {
		long /*int*/ pLink = createShellLink (items[i], directory);
		if (pLink != 0) {
			/*IObjectCollection::AddObject*/
			hr = OS.VtblCall (5, pObjColl, pLink);
			if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
			/*IUnknown::Release*/
			OS.VtblCall (2, pLink);
		}
	}
	/*IUnknown::QueryInterface*/
	hr = OS.VtblCall (0, pObjColl, IID_IObjectArray, ppv);
	if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
	long /*int*/ poa = ppv [0];
	/*IUnknown::Release*/
	OS.VtblCall (2, pObjColl);
	return poa;
}

void destroyItem (TaskItem item) {
	int index = 0;
	while (index < itemCount) {
		if (items [index] == item) break;
		index++;
	}
	if (index == itemCount) return;
	System.arraycopy (items, index + 1, items, index, --itemCount - index);
	items [itemCount] = null;
}

String getDirectory (char[] appName) {
	char [] appDir = new char [appName.length];
	for (int i = 0; i < appName.length; i++) {
		char c = appName [i];
		switch (c) {
			case '\\':
			case '/':
			case ':':
			case '*':
			case '?':
			case '\"':
			case '<':
			case '>':
			case '|':
				appDir [i] = '_';
				break;
			default:
				appDir [i] = c;
		}
	}
	String result = null;
	long /*int*/ [] ppv = new long /*int*/ [1];
	int hr = OS.SHCreateItemInKnownFolder (FOLDERID_LocalAppData, 0, null, IID_IShellItem, ppv);
	if (hr == OS.S_OK) {
		long /*int*/ psiRoot = ppv [0];
		hr = OS.CoCreateInstance (CLSID_FileOperation, 0, OS.CLSCTX_INPROC_SERVER, IID_IFileOperation, ppv);
		if (hr == OS.S_OK) {
			long /*int*/ pfo = ppv [0];
			/*IFileOperation.SetOperationFlags*/
			hr = OS.VtblCall (5, pfo, OS.FOF_NO_UI);
			if (hr == OS.S_OK) {
				long /*int*/ psiAppDir = getDirectory (psiRoot, pfo, appDir, false);
				if (psiAppDir != 0) {
					long /*int*/ psiIcoDir = getDirectory (psiAppDir, pfo, ICO_DIR, true);
					if (psiIcoDir != 0) {
						/*IShellItem::GetDisplayName*/
						hr = OS.VtblCall (5, psiIcoDir, OS.SIGDN_FILESYSPATH, ppv);
						if (hr == OS.S_OK) {
							long /*int*/ wstr = ppv [0]; 
							int length = OS.wcslen (wstr);
							char [] buffer = new char [length];
							OS.MoveMemory (buffer, wstr, length * 2);
							result = new String (buffer);
							OS.CoTaskMemFree (wstr);
						}
						/*IUnknown::Release*/
						OS.VtblCall (2, psiIcoDir);
					}
					/*IUnknown::Release*/
					OS.VtblCall (2, psiAppDir);
				}
			}
			/*IUnknown::Release*/
			OS.VtblCall(2, pfo);
		}
		/*IUnknown::Release*/
		OS.VtblCall (2, psiRoot);
	}
	return result;
}

long /*int*/ getDirectory (long /*int*/ parent, long /*int*/ pfo, char [] name, boolean delete) {
	long /*int*/ [] ppv = new long /*int*/ [1];
	int hr = OS.SHCreateItemFromRelativeName (parent, name, 0, IID_IShellItem, ppv);
	if (hr == OS.S_OK) {
		if (delete) {
			/*IFileOperation.Delete*/
			hr = OS.VtblCall (18, pfo, ppv [0], 0);
			/*IUnknown::Release*/
			OS.VtblCall (2, ppv [0]);
			if (hr == OS.S_OK) {
				/*IFileOperation.NewItem */
				hr = OS.VtblCall (20, pfo, parent, OS.FILE_ATTRIBUTE_DIRECTORY, name, null, 0);
				if (hr == OS.S_OK) {
					/*IFileOperation.PerformOperations */
					hr = OS.VtblCall (21, pfo);
					if (hr == OS.S_OK) {
						hr = OS.SHCreateItemFromRelativeName (parent, name, 0, IID_IShellItem, ppv);
						if (hr == OS.S_OK) {
							return ppv [0];
						}
					}
				}
			}
		} else {
			return ppv [0];
		}
	} else {
		/*IFileOperation.NewItem */
		hr = OS.VtblCall (20, pfo, parent, OS.FILE_ATTRIBUTE_DIRECTORY, name, null, 0);
		if (hr == OS.S_OK) {
			/*IFileOperation.PerformOperations */
			hr = OS.VtblCall (21, pfo);
			if (hr == OS.S_OK) {
				hr = OS.SHCreateItemFromRelativeName (parent, name, 0, IID_IShellItem, ppv);
				if (hr == OS.S_OK) {
					return ppv [0];
				}
			}
		}
	}
	return 0;
}

/**
 * Returns the item at the given, zero-relative index in the
 * receiver. Throws an exception if the index is out of range.
 *
 * @param index the index of the item to return
 * @return the item at the given index
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public TaskItem getItem (int index) {
	checkWidget ();
	createItems ();
	if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE);
	return items [index];
}

/**
 * Returns the <code>TaskItem</code> for the given <code>Shell</code> or the <code>TaskItem</code> 
 * for the application if the <code>Shell</code> parameter is <code>null</code>.
 * If the requested item is not supported by the platform it returns <code>null</code>.
 * 
 * @param shell the shell for which the task item is requested, or null to request the application item
 * @return the task item for the given shell or the application
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public TaskItem getItem (Shell shell) {
	checkWidget ();
	for (int i = 0; i < items.length; i++) {
		if (items [i] != null && items [i].shell == shell) {
			return items [i];
		}
	}
	TaskItem item = new TaskItem (this, SWT.NONE);
	if (shell != null) item.setShell (shell);
	return item;
}

/**
 * Returns the number of items contained in the receiver.
 *
 * @return the number of items
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getItemCount () {
	checkWidget ();
	createItems ();
	return itemCount;
}

/**
 * Returns an array of <code>TaskItem</code>s which are the items
 * in the receiver. 
 * <p>
 * Note: This is not the actual structure used by the receiver
 * to maintain its list of items, so modifying the array will
 * not affect the receiver. 
 * </p>
 *
 * @return the items in the receiver
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public TaskItem [] getItems () {
	checkWidget ();
	createItems ();
	TaskItem [] result = new TaskItem [itemCount];
	System.arraycopy (items, 0, result, 0, result.length);
	return result;
}

void releaseChildren (boolean destroy) {
	if (items != null) {
		for (int i=0; i<items.length; i++) {
			TaskItem item = items [i];
			if (item != null && !item.isDisposed ()) {
				item.release (false);
			}
		}
		items = null;
	}
	super.releaseChildren (destroy);
}

void releaseParent () {
	super.releaseParent ();
	if (display.taskBar == this) display.taskBar = null;
}

void releaseWidget () {
	super.releaseWidget ();
	if (mTaskbarList3 != 0) {
		/* Release() */
		OS.VtblCall (2, mTaskbarList3);
		mTaskbarList3 = 0;
	}
}

void reskinChildren (int flags) {	
	if (items != null) {
		for (int i=0; i<items.length; i++) {
			TaskItem item = items [i];
			if (item != null) item.reskin (flags);
		}
	}
	super.reskinChildren (flags);
}

void setMenu (Menu menu) {
	long /*int*/ [] ppv = new long /*int*/ [1];
	int hr = OS.CoCreateInstance (CLSID_DestinationList, 0, OS.CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, ppv);
	if (hr != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
	long /*int*/ pDestList = ppv[0];
	String appName = Display.APP_NAME;
	char [] buffer = {'S', 'W', 'T', '\0'};
	if (appName != null && appName.length () > 0) {
		int length = appName.length ();
		buffer = new char [length + 1];
		appName.getChars (0, length, buffer, 0);
	}
	
	MenuItem [] items = null; 
	if (menu != null && (items = menu.getItems ()).length != 0) {
		String directory = null;
		for (int i = 0; i < items.length; i++) {
			MenuItem item = items [i];
			if (item.getImage () != null && item.getData (ICON_KEY) == null) {
				directory = getDirectory (buffer);
				break;
			}
		}
		long /*int*/ poa = createShellLinkArray (items, directory);
		if (poa != 0) {
			
			/*ICustomDestinationList::SetAppID*/
			hr = OS.VtblCall (3, pDestList, buffer);
			if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
			
			/*ICustomDestinationList::BeginList*/
			int [] cMaxSlots = new int [1];
			OS.VtblCall (4, pDestList, cMaxSlots, IID_IObjectArray, ppv);
			if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
			long /*int*/ pRemovedItems = ppv [0];
			
			int [] count = new int [1];
			/*IObjectArray::GetCount*/
			OS.VtblCall (3, poa, count);
			if (count [0] != 0) {
				/*ICustomDestinationList::AddUserTasks*/
				hr = OS.VtblCall (7, pDestList, poa);
				if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
			}
			
			for (int i = 0; i < items.length; i++) {
				MenuItem item = items [i];
				if ((item.getStyle () & SWT.CASCADE) != 0) {
					Menu subMenu = item.getMenu ();
					if (subMenu != null) {
						MenuItem [] subItems = subMenu.getItems ();
						if (directory == null) {
							for (int j = 0; j < subItems.length; j++) {
								MenuItem subItem = subItems [j];
								if (subItem.getImage () != null && subItem.getData (ICON_KEY) == null) {
									directory = getDirectory (buffer);
									break;
								}
							}
						}
						long /*int*/ poa2 = createShellLinkArray (subItems, directory);
						if (poa2 != 0) {
							/*IObjectArray::GetCount*/
							OS.VtblCall (3, poa2, count);
							if (count [0] != 0) {
								String text = item.getText ();
								int length = text.length ();
								char [] buffer2 = new char [length + 1];
								text.getChars (0, length, buffer2, 0);
								/*ICustomDestinationList::AppendCategory*/
								hr = OS.VtblCall (5, pDestList, buffer2, poa2);
								if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
							}
							/*IUnknown::Release*/
							OS.VtblCall (2, poa2);
						}
					}
				}
			}
			
			/*ICustomDestinationList::CommitList*/
			hr = OS.VtblCall (8, pDestList);
			if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
			
			/*IUnknown::Release*/
			if (pRemovedItems != 0) OS.VtblCall (2, pRemovedItems);
			/*IUnknown::Release*/
			OS.VtblCall (2, poa);
		}
	} else {
		/*ICustomDestinationList::DeleteList*/
		hr = OS.VtblCall (10, pDestList, buffer);
		if (hr != OS.S_OK) error (SWT.ERROR_INVALID_ARGUMENT);
	}
	/*IUnknown::Release*/
	OS.VtblCall (2, pDestList);
}

}
