Example #1
0
/* Get all possible paths in a color mask without cycles. */
void get_paths(mask_t color_mask, int allow_shrinkers, int *num_moves, move_list_t moves) {
    int i, num_neighbors;
    neighbors_t neighbors;
    path_t path;
    visited_t visited = {{0}};

    /* Repeatedly call build_paths() from each end-point of the color mask */
    for (i = 0; i < NUM_DOTS; i++) {
        if (MASK_CONTAINS(color_mask, i)) {
            get_neighbors(color_mask, i, &num_neighbors, neighbors);
            if (num_neighbors <= 1) {
                build_paths(color_mask, visited, i, allow_shrinkers, num_moves, moves, i, 0, path);
            }
        }
    }
}
Example #2
0
/* Get all unique paths through a color mask with no cycles, starting from an end-point
 * (a dot with only one neighbor). This is accomplished by searching for all paths that
 * connect two end-points, and then computing all of its sub-paths. This uses a modified
 * depth-first search that "fast-forwards" through parts of paths with only one way to go.
 */
void build_paths(
        mask_t color_mask,      /* The color mask that paths are being found in. */
        visited_t visited,      /* Matrix of (start,end) pairs representing visited paths. */
        int start_index,        /* Where to start the path (or where it was started, after recursion). */
        int allow_shrinkers,    /* Whether to generate paths of length 1, which requires a power-up in-game. */
        int *num_moves,         /* Number of moves currently stored in moves. */
        move_list_t moves,      /* Array of moves being generated. */
        int current_index,      /* Current end position of the path. */
        int path_length,        /* Current path length. */
        path_t path             /* Array of indices representing the path. */
        ) {

    int num_neighbors, i;
    neighbors_t neighbors;

    /* Follow the path until the end or an intersection is reached, removing
     * dots as we go to avoid moving backwards.
     */
    get_neighbors(color_mask, current_index, &num_neighbors, neighbors);
    color_mask = REMOVE_FROM_MASK(color_mask, current_index);
    path[path_length++] = current_index;
    while (num_neighbors == 1) {
        current_index = neighbors[0];
        get_neighbors(color_mask, current_index, &num_neighbors, neighbors);
        color_mask = REMOVE_FROM_MASK(color_mask, current_index);
        path[path_length++] = current_index;
    }

    /* If there are no neighbors left (i.e. the end of the path has been reached),
     * then yield the resulting path if it hasn't been visited yet.
     */
    if (num_neighbors == 0) {
        if (!visited[start_index][current_index]) {
            get_subpaths(num_moves, moves, visited, allow_shrinkers, path_length, path);
        }
        return;
    }

    /* Recurse on the remaining branches of the intersection. */
    for (i = 0; i < num_neighbors; i++) {
        build_paths(color_mask, visited, start_index, allow_shrinkers, num_moves, moves, neighbors[i], path_length, path);
    }
}
Example #3
0
static int MCA_do_file_dialog(MCExecPoint& ep, const char *p_title, const char *p_prompt, const char *p_filter, const char *p_initial, unsigned int p_options)
{
	int t_result = 0;

	char *t_initial_file;
	t_initial_file = NULL;

	char *t_initial_folder;
	t_initial_folder = NULL;

	ep . clear();

	if (*p_initial != '\0')
	{
		char *t_initial_clone;
		t_initial_clone = strdup(p_initial);
		MCU_w32path2std(t_initial_clone);
		MCU_fix_path(t_initial_clone);

		if (MCS_exists(t_initial_clone, False))
			t_initial_folder = t_initial_clone;
		else if ((p_options & MCA_OPTION_SAVE_DIALOG) != 0)
		{
			t_initial_file = strrchr(t_initial_clone, '/');
			if (t_initial_file == NULL)
			{
				if (strlen(t_initial_clone) != 0)
					t_initial_file = t_initial_clone;
			}
			else
			{
				*t_initial_file = '\0';
				t_initial_file++;
				
				if (t_initial_file[0] == '\0')
					t_initial_file = NULL;

				if (MCS_exists(t_initial_clone, False))
					t_initial_folder = t_initial_clone;
			}
		}
		else
		{
			char *t_leaf;
			t_leaf = strrchr(t_initial_clone, '/');
			if (t_leaf != NULL)
			{
				*t_leaf = '\0';
				if (MCS_exists(t_initial_clone, False))
					t_initial_folder = t_initial_clone;
			}
		}

		t_initial_file = strdup(t_initial_file);
		t_initial_folder = MCS_resolvepath(t_initial_folder);

		delete t_initial_clone;
	}

	if (!MCModeMakeLocalWindows())
	{
		char ** t_filters = NULL;
		uint32_t t_filter_count = 0;

		if (p_filter != NULL)
		{
			const char *t_strptr = p_filter;
			while (t_strptr[0] != '\0')
			{
				t_filter_count++;
				t_filters = (char**)realloc(t_filters, t_filter_count * sizeof(char*));
				t_filters[t_filter_count - 1] = (char *)t_strptr;
				t_strptr += strlen(t_strptr) + 1;
			}
		}

		MCRemoteFileDialog(ep, p_title, p_prompt, t_filters, t_filter_count, t_initial_folder, t_initial_file, (p_options & MCA_OPTION_SAVE_DIALOG) != 0, (p_options & MCA_OPTION_PLURAL) != 0);

		free(t_filters);
		return 0;
	}

	Window t_window;
	t_window = MCModeGetParentWindow();

	bool t_succeeded;
	int t_filter_index;

	if (MCmajorosversion >= 0x0600)
	{
		static SHCreateItemFromParsingNamePtr  s_shcreateitemfromparsingname = NULL;
		if (s_shcreateitemfromparsingname == NULL)
		{
			static HMODULE s_shell32_module = NULL;
			s_shell32_module = LoadLibraryA("shell32.dll");
			s_shcreateitemfromparsingname = (SHCreateItemFromParsingNamePtr)GetProcAddress(s_shell32_module, "SHCreateItemFromParsingName");
		}

		IFileSaveDialog *t_file_save_dialog;
		IFileOpenDialog *t_file_open_dialog;
		IFileDialog *t_file_dialog;

		t_file_dialog = NULL;

		HRESULT t_hresult;

		if ((p_options & MCA_OPTION_SAVE_DIALOG) == 0)
		{
			t_hresult = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, __uuidof(IFileOpenDialog), (LPVOID *)&t_file_open_dialog);
			t_succeeded = SUCCEEDED(t_hresult);

			t_file_dialog = t_file_open_dialog;
		}
		else
		{
			t_hresult = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, __uuidof(IFileSaveDialog), (LPVOID *)&t_file_save_dialog);
			t_succeeded = SUCCEEDED(t_hresult);

			t_file_dialog = t_file_save_dialog;
		}

		if (t_succeeded)
		{
			DWORD t_options;

			t_options = FOS_FORCEFILESYSTEM | FOS_NOCHANGEDIR | FOS_PATHMUSTEXIST;
			if (p_options & MCA_OPTION_PLURAL)
				t_options |= FOS_ALLOWMULTISELECT;
			if (p_options & MCA_OPTION_SAVE_DIALOG)
				t_options |= FOS_OVERWRITEPROMPT;
			if (p_options & MCA_OPTION_FOLDER_DIALOG)
				t_options |= FOS_PICKFOLDERS;
			else
				t_options |= FOS_FILEMUSTEXIST;

			t_hresult = t_file_dialog -> SetOptions(t_options);
			t_succeeded = SUCCEEDED(t_hresult);
		}

		if (t_succeeded && t_initial_folder != NULL)
		{
			IShellItem *t_initial_folder_shellitem;
			t_initial_folder_shellitem = NULL;
			t_hresult = s_shcreateitemfromparsingname(WideCString(t_initial_folder), NULL, __uuidof(IShellItem), (LPVOID *)&t_initial_folder_shellitem);
			if (SUCCEEDED(t_hresult))
				t_file_dialog -> SetFolder(t_initial_folder_shellitem);
			if (t_initial_folder_shellitem != NULL)
				t_initial_folder_shellitem -> Release();
			t_succeeded = SUCCEEDED(t_hresult);
		}

		if (t_succeeded && t_initial_file != NULL)
		{
			t_hresult = t_file_dialog -> SetFileName(WideCString(t_initial_file));
			t_succeeded = SUCCEEDED(t_hresult);
		}

		if (t_succeeded && p_filter != NULL && (p_options & MCA_OPTION_FOLDER_DIALOG) == 0)
		{
			uint4 t_filter_length, t_filter_count;
			measure_filter(p_filter, t_filter_length, t_filter_count);

			WideCString t_filters(p_filter, t_filter_length);
			COMDLG_FILTERSPEC *t_filter_spec;

			filter_to_spec(t_filters, t_filter_count, t_filter_spec);

			t_hresult = t_file_dialog -> SetFileTypes(t_filter_count, t_filter_spec);
			t_succeeded = SUCCEEDED(t_hresult);

			delete t_filter_spec;
		}

		if (t_succeeded && p_filter != NULL && (p_options & MCA_OPTION_FOLDER_DIALOG) == 0)
		{
			t_hresult = t_file_dialog -> SetFileTypeIndex(1);
			t_succeeded = SUCCEEDED(t_hresult);
		}

		if (t_succeeded)
			t_hresult = t_file_dialog -> SetTitle(WideCString(p_prompt));

		if (t_succeeded)
		{
			t_hresult = t_file_dialog -> Show(t_window != NULL ? (HWND)t_window -> handle . window : NULL);
			t_succeeded = SUCCEEDED(t_hresult);
		}

		if ((p_options & MCA_OPTION_SAVE_DIALOG) == 0)
		{
			IShellItemArray *t_file_items;
			t_file_items = NULL;
			if (t_succeeded)
			{
				t_hresult = t_file_open_dialog -> GetResults(&t_file_items);
				t_succeeded = SUCCEEDED(t_hresult);
			}

			DWORD t_file_item_count;
			if (t_succeeded)
			{
				t_hresult = t_file_items -> GetCount(&t_file_item_count);
				t_succeeded = SUCCEEDED(t_hresult);
			}

			if (t_succeeded)
			{
				ep . clear();
				for(uint4 t_index = 0; t_index < t_file_item_count && t_succeeded; ++t_index)
				{
					IShellItem *t_file_item;
					t_file_item = NULL;
					if (t_succeeded)
					{
						t_hresult = t_file_items -> GetItemAt(t_index, &t_file_item);
						t_succeeded = SUCCEEDED(t_hresult);
					}

					if (t_succeeded)
					{
						t_hresult = append_shellitem_path_and_release(ep, t_file_item, t_index == 0);
						t_succeeded = SUCCEEDED(t_hresult);
					}
				}
			}

			if (t_file_items != NULL)
				t_file_items -> Release();
		}
		else
		{
			IShellItem *t_file_item;
			t_file_item = NULL;
			if (t_succeeded)
			{
				t_hresult = t_file_dialog -> GetResult(&t_file_item);
				t_succeeded = SUCCEEDED(t_hresult);
			}

			if (t_succeeded)
			{
				ep . clear();
				t_hresult = append_shellitem_path_and_release(ep, t_file_item, true);
				t_succeeded = SUCCEEDED(t_hresult);
			}
		}

		t_filter_index = 0;
		if (t_succeeded && (p_options & MCA_OPTION_FOLDER_DIALOG) == 0)
		{
			UINT t_index;
			t_hresult = t_file_dialog -> GetFileTypeIndex(&t_index);
			t_succeeded = SUCCEEDED(t_hresult);
			if (t_succeeded)
				t_filter_index = (int)t_index;
		}

		if (t_file_dialog != NULL)
			t_file_dialog -> Release();

		if (!t_succeeded)
			t_result = t_hresult;
		else
			t_result = 0;
	}
	else
	{
		OPENFILENAMEA t_open_dialog;
		memset(&t_open_dialog, 0, sizeof(OPENFILENAMEA));
		t_open_dialog . lStructSize = sizeof(OPENFILENAMEA);

		char *t_initial_file_buffer = new char[MAX_PATH];
		if (t_initial_file != NULL)
			strcpy(t_initial_file_buffer, t_initial_file);
		else
			*t_initial_file_buffer = '\0';

		t_open_dialog . lpstrFilter = p_filter;
		t_open_dialog . nFilterIndex = 1;
		t_open_dialog . lpstrFile = t_initial_file_buffer;
		t_open_dialog . nMaxFile = MAX_PATH;
		t_open_dialog . lpstrInitialDir = t_initial_folder;
		t_open_dialog . lpstrTitle = p_prompt;
		t_open_dialog . Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR |
														OFN_LONGNAMES | OFN_PATHMUSTEXIST | OFN_EXPLORER |
														OFN_ENABLEHOOK | OFN_ENABLESIZING;

		if (p_options & MCA_OPTION_PLURAL)
			t_open_dialog . Flags |= OFN_ALLOWMULTISELECT;

		if (p_options & MCA_OPTION_SAVE_DIALOG)
			t_open_dialog . Flags |= OFN_OVERWRITEPROMPT;

		t_open_dialog . lpstrFilter = p_filter;
		t_open_dialog . lpfnHook = open_dialog_hook;
		t_open_dialog . hwndOwner = t_window != NULL ? (HWND)t_window -> handle . window : NULL;

		if (p_options & MCA_OPTION_SAVE_DIALOG)
			t_succeeded = GetSaveFileNameA((LPOPENFILENAMEA)&t_open_dialog) == TRUE;
		else
		{
			*t_open_dialog . lpstrFile = '\0';
			t_succeeded = GetOpenFileNameA((LPOPENFILENAMEA)&t_open_dialog) == TRUE;
		}

		if (!t_succeeded)
			t_result = CommDlgExtendedError();

		// MW-2005-07-26: Try again without the specified filename if it was invalid
		if (t_result == FNERR_INVALIDFILENAME)
		{
			*t_open_dialog . lpstrFile = '\0';
			if (p_options & MCA_OPTION_SAVE_DIALOG)
				t_succeeded = GetSaveFileNameA((LPOPENFILENAMEA)&t_open_dialog) == TRUE;
			else
				t_succeeded = GetOpenFileNameA((LPOPENFILENAMEA)&t_open_dialog) == TRUE;

			if (!t_succeeded)
				t_result = CommDlgExtendedError();	
		}

		if (t_result == FNERR_BUFFERTOOSMALL)
			t_succeeded = true;

		if (t_succeeded)
		{
			build_paths(ep);
			t_filter_index = t_open_dialog . nFilterIndex;
		}

		delete t_initial_file_buffer;
	}

	if (t_succeeded)
	{
		if (p_options & MCA_OPTION_RETURN_FILTER)
		{
			const char *t_type = p_filter;
			const char *t_types = p_filter;
			for(int t_index = t_filter_index * 2 - 1; t_index > 1; t_types += 1)
				if (*t_types == '\0')
					t_type = t_types + 1, t_index -= 1;
			MCresult -> copysvalue(t_type);
		}

		t_result = 0;
	}

	waitonbutton();

	if (t_initial_folder != NULL)
		delete t_initial_folder;

	if (t_initial_file != NULL)
		delete t_initial_file;

	return t_result;
}
Example #4
0
// blacklist files or directoies by mounting empty files on top of them
void fs_blacklist(void) {
	char *homedir = cfg.homedir;
	assert(homedir);
	ProfileEntry *entry = cfg.profile;
	if (!entry)
		return;
		
	size_t noblacklist_c = 0;
	size_t noblacklist_m = 32;
	char **noblacklist = calloc(noblacklist_m, sizeof(*noblacklist));

	if (noblacklist == NULL)
		errExit("failed allocating memory for noblacklist entries");

	while (entry) {
		OPERATION op = OPERATION_MAX;
		char *ptr;

		// whitelist commands handled by fs_whitelist()
		if (strncmp(entry->data, "whitelist ", 10) == 0 || *entry->data == '\0') {
			entry = entry->next;
			continue;
		}

		// process bind command
		if (strncmp(entry->data, "bind ", 5) == 0)  {
			char *dname1 = entry->data + 5;
			char *dname2 = split_comma(dname1);
			if (dname2 == NULL) {
				fprintf(stderr, "Error: second directory missing in bind command\n");
				entry = entry->next;
				continue;
			}
			struct stat s;
			if (stat(dname1, &s) == -1) {
				fprintf(stderr, "Error: cannot find directories for bind command\n");
				entry = entry->next;
				continue;
			}
			if (stat(dname2, &s) == -1) {
				fprintf(stderr, "Error: cannot find directories for bind command\n");
				entry = entry->next;
				continue;
			}
			
			// mount --bind olddir newdir
			if (arg_debug)
				printf("Mount-bind %s on top of %s\n", dname1, dname2);
			// preserve dname2 mode and ownership
			if (mount(dname1, dname2, NULL, MS_BIND|MS_REC, NULL) < 0)
				errExit("mount bind");
			/* coverity[toctou] */
			if (chown(dname2, s.st_uid, s.st_gid) == -1)
				errExit("mount-bind chown");
			/* coverity[toctou] */
			if (chmod(dname2, s.st_mode) == -1)
				errExit("mount-bind chmod");
				
			entry = entry->next;
			continue;
		}

		// Process noblacklist command
		if (strncmp(entry->data, "noblacklist ", 12) == 0) {
			if (noblacklist_c >= noblacklist_m) {
                                noblacklist_m *= 2;
                                noblacklist = realloc(noblacklist, sizeof(*noblacklist) * noblacklist_m);
                                if (noblacklist == NULL)
                                        errExit("failed increasing memory for noblacklist entries");
			}
			else
				noblacklist[noblacklist_c++] = expand_home(entry->data + 12, homedir);
			entry = entry->next;
			continue;
		}

		// process blacklist command
		if (strncmp(entry->data, "blacklist ", 10) == 0)  {
			ptr = entry->data + 10;
			op = BLACKLIST_FILE;
		}
		else if (strncmp(entry->data, "blacklist-nolog ", 16) == 0)  {
			ptr = entry->data + 16;
			op = BLACKLIST_NOLOG;
		}
		else if (strncmp(entry->data, "read-only ", 10) == 0) {
			ptr = entry->data + 10;
			op = MOUNT_READONLY;
		}			
		else if (strncmp(entry->data, "tmpfs ", 6) == 0) {
			ptr = entry->data + 6;
			op = MOUNT_TMPFS;
		}			
		else {
			fprintf(stderr, "Error: invalid profile line %s\n", entry->data);
			entry = entry->next;
			continue;
		}

		// replace home macro in blacklist array
		char *new_name = expand_home(ptr, homedir);
		ptr = new_name;

		// expand path macro - look for the file in /bin, /usr/bin, /sbin and  /usr/sbin directories
		if (ptr) {
			if (strncmp(ptr, "${PATH}", 7) == 0) {
				char *fname = ptr + 7;
				size_t fname_len = strlen(fname);
				char **paths = build_paths(); //{"/bin", "/sbin", "/usr/bin", "/usr/sbin", NULL};
				int i = 0;
				while (paths[i] != NULL) {
					char *path = paths[i];
					i++;
					char newname[strlen(path) + fname_len + 1];
					sprintf(newname, "%s%s", path, fname);
					globbing(op, newname, (const char**)noblacklist, noblacklist_c);
				}
			}
			else
				globbing(op, ptr, (const char**)noblacklist, noblacklist_c);
		}

		if (new_name)
			free(new_name);
		entry = entry->next;
	}

	size_t i;
	for (i = 0; i < noblacklist_c; i++) free(noblacklist[i]);
        free(noblacklist);
}
Example #5
0
static int MCA_do_file_dialog(MCStringRef p_title, MCStringRef p_prompt, MCStringRef p_filter, MCStringRef p_initial, unsigned int p_options, MCStringRef &r_value, MCStringRef &r_result)
{
	int t_result = 0;

	MCAutoStringRef t_initial_file;
	MCAutoStringRef t_initial_folder;
    MCAutoStringRef t_initial_native_folder;

	if (p_initial != nil && !MCStringIsEmpty(p_initial))
	{
		MCAutoStringRef t_fixed_path;
		/* UNCHECKED */ MCU_fix_path(p_initial, &t_fixed_path);

		if (MCS_exists(*t_fixed_path, False))
			t_initial_folder = *t_fixed_path;
		else if ((p_options & MCA_OPTION_SAVE_DIALOG) != 0)
		{
			uindex_t t_last_slash;
			if (!MCStringLastIndexOfChar(*t_fixed_path, '/', UINDEX_MAX, kMCStringOptionCompareExact, t_last_slash))
			{
				if (MCStringGetLength(*t_fixed_path) != 0)
					t_initial_file = *t_fixed_path;
			}
			else
			{
				if (t_last_slash < MCStringGetLength(*t_fixed_path) - 1)
					/* UNCHECKED */ MCStringCopySubstring(*t_fixed_path, MCRangeMake(t_last_slash + 1, MCStringGetLength(*t_fixed_path) - (t_last_slash + 1)), &t_initial_file);

				MCAutoStringRef t_folder_split;
				/* UNCHECKED */ MCStringCopySubstring(*t_fixed_path, MCRangeMake(0, t_last_slash - 1), &t_folder_split);
				if (MCS_exists(*t_folder_split, False))
					t_initial_folder = *t_folder_split;
			}
		}
		else
		{
			uindex_t t_last_slash;

			if (MCStringLastIndexOfChar(*t_fixed_path, '/', UINDEX_MAX, kMCStringOptionCompareExact, t_last_slash))
			{
				MCAutoStringRef t_folder_split;
				/* UNCHECKED */ MCStringCopySubstring(*t_fixed_path, MCRangeMake(0, t_last_slash - 1), &t_folder_split);
				
				if (MCS_exists(*t_folder_split, False))
					t_initial_folder = *t_folder_split;
			}
		}
        
        MCAutoStringRef t_resolved_folder;
        /* UNCHECKED */ MCS_resolvepath(*t_initial_folder != nil ? *t_initial_folder : kMCEmptyString, &t_resolved_folder);
        /* UNCHECKED */ MCS_pathtonative(*t_resolved_folder, &t_initial_native_folder);
	}
    
	if (!MCModeMakeLocalWindows())
	{
		MCAutoStringRefArray t_filters;

		if (p_filter != NULL)
		{
			/* UNCHECKED */ MCStringsSplit(p_filter, '\0', t_filters.PtrRef(), t_filters.CountRef());
		}

		MCRemoteFileDialog(p_title, p_prompt, *t_filters, t_filters.Count(), *t_initial_native_folder, *t_initial_file, (p_options & MCA_OPTION_SAVE_DIALOG) != 0, (p_options & MCA_OPTION_PLURAL) != 0, r_value);

		return 0;
	}

	Window t_window;
	t_window = MCModeGetParentWindow();

	MCAutoStringRef t_value;
	bool t_succeeded;
	int t_filter_index;

	if (MCmajorosversion >= 0x0600)
	{
		static SHCreateItemFromParsingNamePtr  s_shcreateitemfromparsingname = NULL;
		if (s_shcreateitemfromparsingname == NULL)
		{
			static HMODULE s_shell32_module = NULL;
			s_shell32_module = LoadLibraryW(L"shell32.dll");
			s_shcreateitemfromparsingname = (SHCreateItemFromParsingNamePtr)GetProcAddress(s_shell32_module, "SHCreateItemFromParsingName");
		}

		IFileSaveDialog *t_file_save_dialog;
		IFileOpenDialog *t_file_open_dialog;
		IFileDialog *t_file_dialog;

		t_file_dialog = NULL;

		HRESULT t_hresult;

		if ((p_options & MCA_OPTION_SAVE_DIALOG) == 0)
		{
			t_hresult = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, __uuidof(IFileOpenDialog), (LPVOID *)&t_file_open_dialog);
			t_succeeded = SUCCEEDED(t_hresult);

			t_file_dialog = t_file_open_dialog;
		}
		else
		{
			t_hresult = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, __uuidof(IFileSaveDialog), (LPVOID *)&t_file_save_dialog);
			t_succeeded = SUCCEEDED(t_hresult);

			t_file_dialog = t_file_save_dialog;
		}

		if (t_succeeded)
		{
			DWORD t_options;

			t_options = FOS_FORCEFILESYSTEM | FOS_NOCHANGEDIR | FOS_PATHMUSTEXIST;
			if (p_options & MCA_OPTION_PLURAL)
				t_options |= FOS_ALLOWMULTISELECT;
			if (p_options & MCA_OPTION_SAVE_DIALOG)
				t_options |= FOS_OVERWRITEPROMPT;
			if (p_options & MCA_OPTION_FOLDER_DIALOG)
				t_options |= FOS_PICKFOLDERS;
			else
				t_options |= FOS_FILEMUSTEXIST;

			t_hresult = t_file_dialog -> SetOptions(t_options);
			t_succeeded = SUCCEEDED(t_hresult);
		}

		if (t_succeeded && *t_initial_native_folder != NULL)
		{
			IShellItem *t_initial_folder_shellitem;
			t_initial_folder_shellitem = NULL;

			MCAutoStringRefAsWString t_initial_folder_wstr;
			/* UNCHECKED */ t_initial_folder_wstr.Lock(*t_initial_native_folder);

			t_hresult = s_shcreateitemfromparsingname(*t_initial_folder_wstr, NULL, __uuidof(IShellItem), (LPVOID *)&t_initial_folder_shellitem);
			if (SUCCEEDED(t_hresult))
				t_file_dialog -> SetFolder(t_initial_folder_shellitem);
			if (t_initial_folder_shellitem != NULL)
				t_initial_folder_shellitem -> Release();
			t_succeeded = SUCCEEDED(t_hresult);
		}

		if (t_succeeded && *t_initial_file != NULL)
		{
			MCAutoStringRefAsWString t_initial_file_wstr;
			/* UNCHECKED */ t_initial_file_wstr.Lock(*t_initial_file);
			
			t_hresult = t_file_dialog -> SetFileName(*t_initial_file_wstr);
			t_succeeded = SUCCEEDED(t_hresult);
		}

		if (t_succeeded && p_filter != NULL && (p_options & MCA_OPTION_FOLDER_DIALOG) == 0)
		{
			uint4 t_filter_length, t_filter_count;
			measure_filter(p_filter, t_filter_length, t_filter_count);

			MCAutoStringRefAsWString t_filter_wstr;
			/* UNCHECKED */ t_filter_wstr.Lock(p_filter);

			COMDLG_FILTERSPEC *t_filter_spec;

			filter_to_spec(*t_filter_wstr, t_filter_count, t_filter_spec);

			t_hresult = t_file_dialog -> SetFileTypes(t_filter_count, t_filter_spec);
			t_succeeded = SUCCEEDED(t_hresult);

			delete t_filter_spec;
		}

		if (t_succeeded && p_filter != NULL && (p_options & MCA_OPTION_FOLDER_DIALOG) == 0)
		{
			t_hresult = t_file_dialog -> SetFileTypeIndex(1);
			t_succeeded = SUCCEEDED(t_hresult);
		}

		if (t_succeeded)
		{
			MCAutoStringRefAsWString t_prompt_wstr;
			/* UNCHECKED */ t_prompt_wstr.Lock(p_prompt);
			t_hresult = t_file_dialog -> SetTitle(*t_prompt_wstr);
		}

		if (t_succeeded)
		{
			t_hresult = t_file_dialog -> Show(t_window != NULL ? (HWND)t_window -> handle . window : NULL);
			t_succeeded = SUCCEEDED(t_hresult);
		}

		if ((p_options & MCA_OPTION_SAVE_DIALOG) == 0)
		{
			IShellItemArray *t_file_items;
			t_file_items = NULL;
			if (t_succeeded)
			{
				t_hresult = t_file_open_dialog -> GetResults(&t_file_items);
				t_succeeded = SUCCEEDED(t_hresult);
			}

			DWORD t_file_item_count;
			if (t_succeeded)
			{
				t_hresult = t_file_items -> GetCount(&t_file_item_count);
				t_succeeded = SUCCEEDED(t_hresult);
			}

			if (t_succeeded)
			{
				for(uint4 t_index = 0; t_index < t_file_item_count && t_succeeded; ++t_index)
				{
					IShellItem *t_file_item;
					t_file_item = NULL;
					if (t_succeeded)
					{
						t_hresult = t_file_items -> GetItemAt(t_index, &t_file_item);
						t_succeeded = SUCCEEDED(t_hresult);
					}

					if (t_succeeded)
					{
						t_hresult = append_shellitem_path_and_release(t_file_item, t_index == 0, &t_value);
						t_succeeded = SUCCEEDED(t_hresult);
					}
				}
			}

			if (t_file_items != NULL)
				t_file_items -> Release();
		}
		else
		{
			IShellItem *t_file_item;
			t_file_item = NULL;
			if (t_succeeded)
			{
				t_hresult = t_file_dialog -> GetResult(&t_file_item);
				t_succeeded = SUCCEEDED(t_hresult);
			}

			if (t_succeeded)
			{
				t_hresult = append_shellitem_path_and_release(t_file_item, true, &t_value);
				t_succeeded = SUCCEEDED(t_hresult);
			}
		}

		t_filter_index = 0;
		if (t_succeeded && (p_options & MCA_OPTION_FOLDER_DIALOG) == 0)
		{
			UINT t_index;
			t_hresult = t_file_dialog -> GetFileTypeIndex(&t_index);
			t_succeeded = SUCCEEDED(t_hresult);
			if (t_succeeded)
				t_filter_index = (int)t_index;
		}

		if (t_file_dialog != NULL)
			t_file_dialog -> Release();

		if (!t_succeeded)
			t_result = t_hresult;
		else
			t_result = 0;
	}
	else
	{
		OPENFILENAMEW t_open_dialog;
		memset(&t_open_dialog, 0, sizeof(OPENFILENAMEW));
		t_open_dialog . lStructSize = sizeof(OPENFILENAMEW);

		MCAutoStringRefAsWString t_initial_folder_wstr;
		MCAutoStringRefAsWString t_prompt_wstr;
		MCAutoStringRefAsWString t_filter_wstr;
		/* UNCHECKED */ t_filter_wstr.Lock(p_filter);
		/* UNCHECKED */ t_initial_folder_wstr.Lock(*t_initial_native_folder);
		/* UNCHECKED */ t_prompt_wstr.Lock(p_prompt);

		MCAutoArray<unichar_t> t_buffer;
		/* UNCHECKED */ t_buffer.New(MAX_PATH);

		if (!MCStringIsEmpty(*t_initial_file))
			/* UNCHECKED */ MCStringGetChars(*t_initial_file, MCRangeMake(0, t_buffer.Size()), t_buffer.Ptr());
		else
			t_buffer[0] = '\0';

		t_open_dialog . lpstrFilter = *t_filter_wstr;
		t_open_dialog . nFilterIndex = 1;
		t_open_dialog . lpstrFile = t_buffer.Ptr();
		t_open_dialog . nMaxFile = t_buffer.Size();
		t_open_dialog . lpstrInitialDir = *t_initial_folder_wstr;
		t_open_dialog . lpstrTitle = *t_prompt_wstr;
		t_open_dialog . Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR |
														OFN_LONGNAMES | OFN_PATHMUSTEXIST | OFN_EXPLORER |
														OFN_ENABLEHOOK | OFN_ENABLESIZING;

		if (p_options & MCA_OPTION_PLURAL)
			t_open_dialog . Flags |= OFN_ALLOWMULTISELECT;

		if (p_options & MCA_OPTION_SAVE_DIALOG)
			t_open_dialog . Flags |= OFN_OVERWRITEPROMPT;

		t_open_dialog . lpstrFilter = *t_filter_wstr;
		t_open_dialog . lpfnHook = open_dialog_hook;
		t_open_dialog . hwndOwner = t_window != NULL ? (HWND)t_window -> handle . window : NULL;

		if (p_options & MCA_OPTION_SAVE_DIALOG)
			t_succeeded = GetSaveFileNameW(&t_open_dialog) == TRUE;
		else
		{
			*t_open_dialog . lpstrFile = '\0';
			t_succeeded = GetOpenFileNameW(&t_open_dialog) == TRUE;
		}

		if (!t_succeeded)
			t_result = CommDlgExtendedError();

		// MW-2005-07-26: Try again without the specified filename if it was invalid
		if (t_result == FNERR_INVALIDFILENAME)
		{
			*t_open_dialog . lpstrFile = '\0';
			if (p_options & MCA_OPTION_SAVE_DIALOG)
				t_succeeded = GetSaveFileNameW(&t_open_dialog) == TRUE;
			else
				t_succeeded = GetOpenFileNameW(&t_open_dialog) == TRUE;

			if (!t_succeeded)
				t_result = CommDlgExtendedError();	
		}

		if (t_result == FNERR_BUFFERTOOSMALL)
			t_succeeded = true;

		if (t_succeeded)
		{
			build_paths(&t_value);
			t_filter_index = t_open_dialog . nFilterIndex;
		}
	}

	if (t_succeeded)
	{
		if (p_options & MCA_OPTION_RETURN_FILTER)
		{
			// The filter string has the following format:
			// "<description0>\0<extensions0>\0<description1>\0...\0<extensionsN>\0"
			// so the n'th filter comes after the 2(n - 1)'th null character
			uindex_t t_index = 2 * (t_filter_index - 1);
			uindex_t t_offset = 0;
			while (t_index--)
			{
				/* UNCHECKED */ MCStringFirstIndexOfChar(p_filter, '\0', t_offset, kMCStringOptionCompareExact, t_offset);
				t_offset++;
			}
			
			uindex_t t_end;
			t_end = UINDEX_MAX;
			/* UNCHECKED */ MCStringFirstIndexOfChar(p_filter, '\0', t_offset, kMCStringOptionCompareExact, t_end);
            
			/* UNCHECKED */ MCStringCopySubstring(p_filter, MCRangeMake(t_offset, t_end-t_offset), r_result);
		}

		t_result = 0;
		r_value = MCValueRetain(*t_value);
	}
	else
		r_result = MCValueRetain(MCNameGetString(MCN_cancel));

	waitonbutton();

	return t_result;
}