Example #1
0
// Run a program completely detached from the current process
// it runs independantly.  Program does not suspend until it completes.
// No way at all to know if the program works or fails.
SYSTEM_PROC( PTASK_INFO, LaunchPeerProgramExx )( CTEXTSTR program, CTEXTSTR path, PCTEXTSTR args
															  , int flags
															  , TaskOutput OutputHandler
															  , TaskEnd EndNotice
															  , uintptr_t psv
																DBG_PASS
															  )
{
	PTASK_INFO task;
	if( program && program[0] )
	{
#ifdef WIN32
		int launch_flags = ( ( flags & LPP_OPTION_NEW_CONSOLE ) ? CREATE_NEW_CONSOLE : 0 )
		                 | ( ( flags & LPP_OPTION_NEW_GROUP ) ? CREATE_NEW_PROCESS_GROUP : 0 )
			;
		PVARTEXT pvt = VarTextCreateEx( DBG_VOIDRELAY );
		PTEXT cmdline;
		PTEXT final_cmdline;
		LOGICAL needs_quotes;
		TEXTSTR expanded_path = ExpandPath( program );
		char *new_path;
		TEXTSTR expanded_working_path = path?ExpandPath( path ):ExpandPath( WIDE(".") );
		int first = TRUE;
		//TEXTCHAR saved_path[256];
		task = (PTASK_INFO)AllocateEx( sizeof( TASK_INFO ) DBG_RELAY );
		MemSet( task, 0, sizeof( TASK_INFO ) );
		task->psvEnd = psv;
		task->EndNotice = EndNotice;
		if( l.ExternalFindProgram ) {
			new_path = l.ExternalFindProgram( expanded_path );
			if( new_path ) {
				Release( expanded_path );
				expanded_path = new_path;
			}
		}
#ifdef _DEBUG
		xlprintf(LOG_NOISE)( WIDE("%s[%s]"), path, expanded_working_path );
#endif
		if( StrCmp( path, WIDE(".") ) == 0 )
		{
			path = NULL;
			Release( expanded_working_path );
			expanded_working_path = NULL;
		}
		if( expanded_path && StrChr( expanded_path, ' ' ) )
			needs_quotes = TRUE;
		else
			needs_quotes = FALSE;


		if( needs_quotes )
			vtprintf( pvt, WIDE( "\"" ) );

      /*
		if( !IsAbsolutePath( expanded_path ) && expanded_working_path )
		{
			//lprintf( "needs working path too" );
			vtprintf( pvt, WIDE("%s/"), expanded_working_path );
		}
      */
		vtprintf( pvt, WIDE("%s"), expanded_path );

		if( needs_quotes )
			vtprintf( pvt, WIDE( "\"" ) );

		if( flags & LPP_OPTION_FIRST_ARG_IS_ARG )
			;
		else
		{
			if( args && args[0] )// arg[0] is passed with linux programs, and implied with windows.
				args++;
		}
		while( args && args[0] )
		{
			if( args[0][0] == 0 )
				vtprintf( pvt, WIDE( " \"\"" ) );
			else if( StrChr( args[0], ' ' ) )
				vtprintf( pvt, WIDE(" \"%s\""), args[0] );
			else
				vtprintf( pvt, WIDE(" %s"), args[0] );
			first = FALSE;
			args++;
		}
		cmdline = VarTextGet( pvt );
		vtprintf( pvt, WIDE( "cmd.exe /c %s" ), GetText( cmdline ) );
		final_cmdline = VarTextGet( pvt );
		VarTextDestroy( &pvt );
		MemSet( &task->si, 0, sizeof( STARTUPINFO ) );
		task->si.cb = sizeof( STARTUPINFO );

#ifdef _DEBUG
		xlprintf(LOG_NOISE)( WIDE( "quotes?%s path [%s] program [%s]  [cmd.exe (%s)]"), needs_quotes?WIDE( "yes"):WIDE( "no"), expanded_working_path, expanded_path, GetText( final_cmdline ) );
#endif
      /*
		if( path )
		{
			GetCurrentPath( saved_path, sizeof( saved_path ) );
			SetCurrentPath( path );
		}
      */
		task->OutputEvent = OutputHandler;
		if( OutputHandler )
		{
			SECURITY_ATTRIBUTES sa;

			sa.bInheritHandle = TRUE;
			sa.lpSecurityDescriptor = NULL;
			sa.nLength = sizeof( sa );

			CreatePipe( &task->hReadOut, &task->hWriteOut, &sa, 0 );
			//CreatePipe( &hReadErr, &hWriteErr, &sa, 0 );
			CreatePipe( &task->hReadIn, &task->hWriteIn, &sa, 0 );
			task->si.hStdInput = task->hReadIn;
			task->si.hStdError = task->hWriteOut;
			task->si.hStdOutput = task->hWriteOut;
			task->si.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
			if( !( flags & LPP_OPTION_DO_NOT_HIDE ) )
				task->si.wShowWindow = SW_HIDE;
			else
				task->si.wShowWindow = SW_SHOW;
		}
		else
		{
			task->si.dwFlags |= STARTF_USESHOWWINDOW;
			if( !( flags & LPP_OPTION_DO_NOT_HIDE ) )
				task->si.wShowWindow = SW_HIDE;
			else
				task->si.wShowWindow = SW_SHOW;
		}

		{
			HINSTANCE hShellProcess = 0;
			int success = 0;
#ifdef WIN32
			if( flags & LPP_OPTION_IMPERSONATE_EXPLORER )
			{
				HANDLE hExplorer = GetImpersonationToken();
				if( ( CreateProcessAsUser( hExplorer, NULL //program
												 , GetText( cmdline )
												 , NULL, NULL, TRUE
												 , launch_flags | CREATE_NEW_PROCESS_GROUP
												 , NULL
												 , expanded_working_path
												 , &task->si
												 , &task->pi ) || FixHandles(task) || DumpError() ) ||
					( CreateProcessAsUser( hExplorer, program
												, GetText( cmdline )
												, NULL, NULL, TRUE
												, launch_flags | CREATE_NEW_PROCESS_GROUP
												, NULL
												, expanded_working_path
												, &task->si
												, &task->pi ) || FixHandles(task) || DumpError() ) ||
					( CreateProcessAsUser( hExplorer, program
												, NULL // GetText( cmdline )
												, NULL, NULL, TRUE
												, launch_flags | CREATE_NEW_PROCESS_GROUP
												, NULL
												, expanded_working_path
												, &task->si
												, &task->pi ) || FixHandles(task) || DumpError() ) ||
					( CreateProcessAsUser( hExplorer, WIDE( "cmd.exe" )
												, GetText( final_cmdline )
												, NULL, NULL, TRUE
												, launch_flags | CREATE_NEW_PROCESS_GROUP
												, NULL
												, expanded_working_path
												, &task->si
												, &task->pi ) || FixHandles(task) || DumpError() )
				  )
				{
					success = 1;
				}
				CloseHandle( hExplorer );
			}
			else
#endif
			{
				if( ( CreateProcess( NULL //program
										 , GetText( cmdline )
										 , NULL, NULL, TRUE
										 , launch_flags | ( OutputHandler?CREATE_NO_WINDOW:0 )//CREATE_NEW_PROCESS_GROUP
										 , NULL
										 , expanded_working_path
										 , &task->si
										 , &task->pi ) || FixHandles(task) || DumpError() ) ||
					( CreateProcess( program
										, GetText( cmdline )
										, NULL, NULL, TRUE
										, launch_flags | ( OutputHandler?CREATE_NO_WINDOW:0 )//CREATE_NEW_PROCESS_GROUP
										, NULL
										, expanded_working_path
										, &task->si
										, &task->pi ) || FixHandles(task) || DumpError() ) ||
					( CreateProcess( program
										, NULL // GetText( cmdline )
										, NULL, NULL, TRUE
										, launch_flags | ( OutputHandler?CREATE_NO_WINDOW:0 )//CREATE_NEW_PROCESS_GROUP
										, NULL
										, expanded_working_path
										, &task->si
										, &task->pi ) || FixHandles(task) || DumpError() ) ||
					( TryShellExecute( task, expanded_working_path, program, cmdline ) ) ||
					( CreateProcess( NULL//WIDE( "cmd.exe" )
										, GetText( final_cmdline )
										, NULL, NULL, TRUE
										, launch_flags | ( OutputHandler?CREATE_NO_WINDOW:0 )//CREATE_NEW_PROCESS_GROUP
										, NULL
										, expanded_working_path
										, &task->si
										, &task->pi ) || FixHandles(task) || DumpError() ) ||
               0
				  )
				{
					success = 1;
				}
			}
			if( success )
			{
				//CloseHandle( task->hReadIn );
				//CloseHandle( task->hWriteOut );
#ifdef _DEBUG
				xlprintf(LOG_NOISE)( WIDE("Success running %s[%s] in %s (%p): %d"), program, GetText( cmdline ), expanded_working_path, task->pi.hProcess, GetLastError() );
#endif
				if( OutputHandler )
				{
					task->hStdIn.handle 	= task->hWriteIn;
					task->hStdIn.pLine 	= NULL;
					//task->hStdIn.pdp 		= pdp;
					task->hStdIn.hThread  = 0;
					task->hStdIn.bNextNew = TRUE;

					task->hStdOut.handle 	 = task->hReadOut;
					task->hStdOut.pLine 	 = NULL;
					//task->hStdOut.pdp 		 = pdp;
					task->hStdOut.bNextNew = TRUE;
					task->hStdOut.hThread  = ThreadTo( HandleTaskOutput, (uintptr_t)task );
					ThreadTo( WaitForTaskEnd, (uintptr_t)task );
				}
				else
				{
					//task->hThread =
					ThreadTo( WaitForTaskEnd, (uintptr_t)task );
				}
			}
			else
			{
				xlprintf(LOG_NOISE)( WIDE("Failed to run %s[%s]: %d"), program, GetText( cmdline ), GetLastError() );
				CloseHandle( task->hWriteIn );
				CloseHandle( task->hReadIn );
				CloseHandle( task->hWriteOut );
				CloseHandle( task->hReadOut );
				CloseHandle( task->pi.hProcess );
				CloseHandle( task->pi.hThread );
				Release( task );
				task = NULL;
			}
		}
		LineRelease( cmdline );
		LineRelease( final_cmdline );
		Release( expanded_working_path );
		Release( expanded_path );
      /*
      if( path )
		SetCurrentPath( saved_path );
      */
		return task;
#endif
#ifdef __LINUX__
		{
			pid_t newpid;
			TEXTCHAR saved_path[256];
         xlprintf(LOG_ALWAYS)( WIDE("Expand Path was not implemented in linux code!") );
			task = (PTASK_INFO)Allocate( sizeof( TASK_INFO ) );
			MemSet( task, 0, sizeof( TASK_INFO ) );
			task->psvEnd = psv;
			task->EndNotice = EndNotice;
			task->OutputEvent = OutputHandler;
         if( OutputHandler )
			{
				pipe(task->hStdIn.pair);
				task->hStdIn.handle = task->hStdIn.pair[1];

				pipe(task->hStdOut.pair);
				task->hStdOut.handle = task->hStdOut.pair[0];
			}

			// always have to thread to taskend so waitpid can clean zombies.
			ThreadTo( WaitForTaskEnd, (uintptr_t)task );
			if( path )
			{
				GetCurrentPath( saved_path, sizeof( saved_path ) );
				SetCurrentPath( path );
			}
			if( !( newpid = fork() ) )
			{
            char *_program = CStrDup( program );
				// in case exec fails, we need to
				// drop any registered exit procs...
				//close( task->hStdIn.pair[1] );
				//close( task->hStdOut.pair[0] );
				//close( task->hStdErr.pair[0] );
				if( OutputHandler ) {
					dup2( task->hStdIn.pair[0], 0 );
					dup2( task->hStdOut.pair[1], 1 );
					dup2( task->hStdOut.pair[1], 2 );
				}
				DispelDeadstart();

				//usleep( 100000 );
				execve( _program, (char *const*)args, environ );
				lprintf( WIDE( "Direct execute failed... trying along path..." ) );
				{
					char *tmp = strdup( getenv( "PATH" ) );
					char *tok;
					for( tok = strtok( tmp, ":" ); tok; tok = strtok( NULL, ":" ) )
					{
						char fullname[256];
						snprintf( fullname, sizeof( fullname ), "%s/%s", tok, _program );

						lprintf( WIDE( "program:[%s]" ), fullname );
						((char**)args)[0] = fullname;
						execve( fullname, (char*const*)args, environ );
					}
					Release( tmp );
				}
				if( OutputHandler ) {
					close( task->hStdIn.pair[0] );
					close( task->hStdOut.pair[1] );
				}
				//close( task->hWriteErr );
				close( 0 );
				close( 1 );
				close( 2 );
				lprintf( WIDE( "exec failed - and this is ALLL bad... %d" ), errno );
				//DebugBreak();
				// well as long as this runs before
				// the other all will be well...
				task = NULL;
				// shit - what can I do now?!
				exit(0); // just in case exec fails... need to fault this.
			}
			else
			{
				if( OutputHandler ) {
					close( task->hStdIn.pair[0] );
					close( task->hStdOut.pair[1] );
				}
			}
			if( OutputHandler )
				ThreadTo( HandleTaskOutput, (uintptr_t)task );
			task->pid = newpid;
			lprintf( WIDE("Forked, and set the pid..") );
			// how can I know if the command failed?
			// well I can't - but the user's callback will be invoked
			// when the above exits.
			if( path )
			{
				// if path is NULL we didn't change the path...
				SetCurrentPath( saved_path );
			}
			return task;
		}
#endif
	}
	return FALSE;
}
Example #2
0
 int  ScanFilesEx ( CTEXTSTR base
           , CTEXTSTR mask
           , void **pInfo
           , void CPROC Process( uintptr_t psvUser, CTEXTSTR name, int flags )
           , int flags 
           , uintptr_t psvUser 
		   , LOGICAL begin_sub_path 
		   , struct file_system_mounted_interface *mount
		   )
{
	PMFD pDataCurrent = (PMFD)(pInfo);
	PMFD pData = (PMFD)(*pInfo);
	TEXTSTR tmp_base = NULL;
	int sendflags;
	int processed = 0;
#ifndef WIN32
	struct dirent *de;
#endif
	if( begin_sub_path )
	{
		pInfo = (void**)&(pDataCurrent->current);
	}
	else
		pDataCurrent = NULL;

	//lprintf( "Search in %s for %s   %d %d", base?base:"(NULL)", mask?mask:"(*)", (*pInfo)?((PMFD)*pInfo)->scanning_mount:0, (*pInfo)?((PMFD)*pInfo)->single_mount:0 );
	if( !*pInfo || begin_sub_path || ((PMFD)*pInfo)->new_mount )
	{
		TEXTCHAR findmask[256];
		pData = (PMFD)(*pInfo);
		if( !pData )
		{
			*pInfo = Allocate( sizeof( MFD ) );
			pData = (PMFD)(*pInfo);
			if( !( pData->scanning_mount = mount ) )
			{
				if( !winfile_local )
					SimpleRegisterAndCreateGlobal( winfile_local );

				//lprintf( "... %p", winfile_local );
				pData->single_mount = FALSE;
				pData->scanning_mount = (*winfile_local).mounted_file_systems;
			}
			else
				pData->single_mount = TRUE;

			if( !pData->scanning_mount )
			{
				Deallocate( PMFD, pData );
				if( tmp_base )
					Release( tmp_base );
				return 0;
			}
			if( pData->scanning_mount->fsi )
			{
				//lprintf( "create cursor" );
				tmp_base = ExpandPathEx( base, pData->scanning_mount->fsi );
				pData->cursor = pData->scanning_mount->fsi->find_create_cursor( pData->scanning_mount->psvInstance, CStrDup( tmp_base ), CStrDup( mask ) );
			}
			else
			{
				//lprintf( "no cursor" );
				pData->cursor = NULL;
			}
		}
		else
		{
			if( pData->new_mount )
			{
				if( pData->scanning_mount->fsi )
				{
					//lprintf( "create cursor (new mount)" );
					tmp_base = ExpandPathEx( base, pData->scanning_mount->fsi );
					pData->cursor = pData->scanning_mount->fsi->find_create_cursor( pData->scanning_mount->psvInstance, CStrDup( tmp_base ), CStrDup( mask ) );
				}
				else
					pData->cursor = NULL;
			}
		}
		pData->new_mount = FALSE;
		pData->current = NULL;
		pData->prior = pDataCurrent;

		if( pDataCurrent )
		{
			pData->root_info = pDataCurrent->root_info;
			pInfo = (void**)pData->root_info;
		}
		else
		{
			pData->root_info = (struct myfinddata**)pInfo;
		}

		(*pData->root_info) = pData;
		if( base )
		{
			TEXTSTR tmp;
			StrCpyEx( findbasename(pInfo), tmp = ExpandPathEx( base, pData->scanning_mount?pData->scanning_mount->fsi:NULL ), MAX_PATH_NAME );
			Release( tmp );
			StrCpyEx( findmask(pInfo), mask, MAX_PATH_NAME );
		}
		else
		{
			CTEXTSTR p = pathrchr( mask );
			if( p )
			{
				StrCpyEx( findbasename(pInfo), mask, p - mask + 1 );
				StrCpyEx( findmask(pInfo), p + 1, MAX_PATH_NAME );
				//mask = p + 1;
			}
			else
			{
				StrCpyEx( findbasename(pInfo), WIDE(""), 2 );
				StrCpyEx( findmask(pInfo), mask, MAX_PATH_NAME );
			}
		}
		if( findbasename(pInfo)[0] )
			tnprintf( findmask, sizeof(findmask), WIDE("%s/*"), findbasename(pInfo) );
		else
			tnprintf( findmask, sizeof( findmask ), WIDE( "*" ) );
		if( pData->scanning_mount?pData->scanning_mount->fsi:NULL )
			if( pData->scanning_mount->fsi->find_first( findcursor(pInfo) ) )
				findhandle(pInfo) = 0;
			else
				findhandle(pInfo) = (HANDLECAST)-1;
		else
		{
#if WIN32
			findhandle(pInfo) = findfirst( findmask, finddata(pInfo) );
#else
			//lprintf( "opendir %s", findbasename(pInfo) );
			findhandle( pInfo ) = opendir( findbasename(pInfo) );
			if( !findhandle(pInfo ) )
				findhandle(pInfo) = (HANDLECAST)-1;
			else
				de = readdir( (DIR*)findhandle( pInfo ) );
#endif
		}
		if( findhandle(pInfo) == (HANDLECAST)-1 )
		{
			PMFD prior = pData->prior;
			//lprintf( "first use of cursor or first open of directoy failed..." );
			if( pData->scanning_mount && pData->scanning_mount->fsi )
				pData->scanning_mount->fsi->find_close( (struct find_cursor*)findcursor(pInfo) );
			else
			{
#ifdef WIN32
				findclose( findhandle(pInfo) );
#else
				// but it failed... so ... don't close
				//closedir( findhandle( pInfo ) );
#endif
			}
			pData->scanning_mount = NextThing( pData->scanning_mount );
			if( !pData->scanning_mount || pData->single_mount )
			{
				(*pData->root_info) = pData->prior;
				if( !begin_sub_path ) {
					Release( pData ); pInfo[0] = NULL;
				}
				//lprintf( WIDE( "%p %d" ), prior, processed );
				if( tmp_base )
					Release( tmp_base );
				return prior?processed:0;
			}
			pData->new_mount = TRUE;
				if( tmp_base )
					Release( tmp_base );
			return 1;
		}
	}
	else
	{
		int r;
getnext:
		//lprintf( "returning customer..." );
		if( pData->scanning_mount?pData->scanning_mount->fsi:NULL )
			r = !pData->scanning_mount->fsi->find_next( findcursor( pInfo ) );
		else
		{
#ifdef _WIN32
			r = findnext( findhandle(pInfo), finddata( pInfo ) );
#else
			de = readdir( (DIR*)findhandle( pInfo ) );
			//lprintf( "using %p got %p", findhandle( pInfo ), de );
			r = (de == NULL);
#endif
		}
		if( r )
		{
			PMFD prior = pData->prior;
			//lprintf( "nothing left to find..." );
			if( pData->scanning_mount->fsi )
				pData->scanning_mount->fsi->find_close( findcursor(pInfo) );
			else
			{
#ifdef WIN32
				findclose( findhandle(pInfo) );
#else
				closedir( (DIR*)findhandle(pInfo));
#endif
			}
			pData->scanning_mount = NextThing( pData->scanning_mount );
			//lprintf( "Step mount... %p %d", pData->scanning_mount, pData->single_mount );
			if( !pData->scanning_mount || pData->single_mount )
			{
				//lprintf( "done with mounts?" );
				(*pData->root_info) = pData->prior;
				Release( pData );
				if( prior )
					prior->current = NULL;
				if( !processed && !begin_sub_path )
				{
					//pInfo = (void**)&(prior->prior->current);
					pData = prior;
					if( pData )
						goto getnext;
				}
				if( tmp_base )
					Release( tmp_base );
				return (*pInfo)?processed:0;
			}
			pData->new_mount = TRUE;
			if( tmp_base )
				Release( tmp_base );
			return 1;
		}
	}
	if( pData->scanning_mount?pData->scanning_mount->fsi:NULL )
	{
		char * path = pData->scanning_mount->fsi->find_get_name( findcursor(pInfo) );
		//lprintf( "... %s", path );
		if( !strcmp( ".", path ) ||
		    !strcmp( "..", path ) )
		goto getnext;
	}
	else
	{
#if WIN32 
		//lprintf( "... %s", finddata(pInfo)->name );
#  ifdef UNDER_CE
		if( !StrCmp( WIDE("."), finddata(pInfo)->cFileName ) ||
		    !StrCmp( WIDE(".."), finddata(pInfo)->cFileName ) )
#  else
		if( !StrCmp( WIDE("."), finddata(pInfo)->name ) ||
		    !StrCmp( WIDE(".."), finddata(pInfo)->name ) )
#  endif
#else
		if( !StrCmp( WIDE("."), de->d_name ) ||
		    !StrCmp( WIDE(".."), de->d_name ) )
#endif
			goto getnext;
	}
	if( !(flags & SFF_NAMEONLY) ) // if nameonly - have to rebuild the correct name.
	{
		if( pData->scanning_mount?pData->scanning_mount->fsi:NULL )
		{
			tnprintf( pData->file_buffer, MAX_PATH_NAME, WIDE("%s"), pData->scanning_mount->fsi->find_get_name( findcursor(pInfo) ) );
			if( findbasename( pInfo )[0] )
				tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s/%s"), findbasename(pInfo), pData->file_buffer );
			else
				tnprintf( pData->buffer, MAX_PATH_NAME, WIDE( "%s" ), pData->file_buffer );
		}
		else
		{
#ifdef WIN32
#  ifdef UNDER_CE
			tnprintf( pData->file_buffer, MAX_PATH_NAME, WIDE( "%s" ), finddata( pInfo )->cFileName );
			tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s/%s"), findbasename(pInfo), finddata(pInfo)->cFileName );
#  else
			tnprintf( pData->file_buffer, MAX_PATH_NAME, WIDE("%s"), finddata(pInfo)->name );
			tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s%s%s"), findbasename(pInfo), findbasename( pInfo )[0]?"/":"", pData->file_buffer );
#  endif
#else
			tnprintf( pData->file_buffer, MAX_PATH_NAME, WIDE("%s"), de->d_name );
			tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s/%s"), findbasename(pInfo), de->d_name );
#endif
		}
	}
	else
	{
		if( flags & SFF_SUBCURSE )
		{
			if( pData->scanning_mount?pData->scanning_mount->fsi:NULL )
			{
				tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s%s%s")
					  , pData->prior?pData->prior->buffer:WIDE( "" )
					  , pData->prior?WIDE( "/" ):WIDE( "" )
					, pData->scanning_mount->fsi->find_get_name( findcursor(pInfo) ) 
					);
			}
			else
			{
#if WIN32
#  ifdef UNDER_CE
				tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s%s%s")
						  , pData->prior?pData->prior->buffer:WIDE( "" )
						  , pData->prior?WIDE( "/" ):WIDE( "" )
						  , finddata(pInfo)->cFileName );
#  else
				tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s%s%s")
						  , pData->prior?pData->prior->buffer:WIDE( "" )
						  , pData->prior?WIDE( "/" ):WIDE( "" )
						  , finddata(pInfo)->name );
#  endif
#else
				tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s%s%s")
					  , pData->prior?pData->prior->buffer:WIDE( "" )
					  , pData->prior?WIDE( "/" ):WIDE( "" )
					  , de->d_name );
					  lprintf( "resulting is %s", pData->buffer );
#endif
			}
		}
		else
		{
			if( pData->scanning_mount?pData->scanning_mount->fsi:NULL )
			{
				tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s"), pData->scanning_mount->fsi->find_get_name( findcursor(pInfo) ) );
			}
			else
			{
#if WIN32
#  ifdef UNDER_CE
				tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s"), finddata(pInfo)->cFileName );
#  else
#    ifdef UNICODE
				snwprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s"), finddata(pInfo)->name );
#    else
				tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s"), finddata(pInfo)->name );
#    endif
#  endif
#else
				tnprintf( pData->buffer, MAX_PATH_NAME, WIDE("%s"), de->d_name );
#endif
			}
		}
	}
	pData->buffer[MAX_PATH_NAME-1] = 0; // force nul termination...
#ifdef UNICODE
	{
		char *pDataBuffer = CStrDup( pData->buffer );
#else
#  define pDataBuffer pData->buffer
#endif
	//lprintf( "Check if %s is a directory...", pData->buffer );
	if( (flags & (SFF_DIRECTORIES | SFF_SUBCURSE))
		&& (pData->scanning_mount && pData->scanning_mount->fsi
			&& (pData->scanning_mount->fsi->is_directory
				&& pData->scanning_mount->fsi->is_directory( pDataBuffer )))
		|| (!(pData->scanning_mount ? pData->scanning_mount->fsi : NULL)
#ifdef WIN32
#  ifdef UNDER_CE
			&& (finddata( pInfo )->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
#  else
			&& (finddata( pInfo )->attrib & _A_SUBDIR)
#  endif
#else
			&& IsPath( pData->buffer )
#endif
			) )
	{
#ifdef UNICODE
		Deallocate( char *, pDataBuffer );
#else 
#  undef pDataBuffer
#endif
		//lprintf( "... it is?" );
		if( flags & SFF_DIRECTORIES )
		{
			if( Process != NULL )
			{
				//lprintf( "Send %s", pData->buffer );
				Process( psvUser, pData->buffer, SFF_DIRECTORY );
				processed = 1;
			}
			//return 1;
		}
		if( flags & SFF_SUBCURSE )
		{
			void *data = NULL;
			int ofs = 0;
			TEXTCHAR tmpbuf[MAX_PATH_NAME];
			if( flags & SFF_NAMEONLY )
			{
				// even in name only - need to have this full buffer for subcurse.
				if( pData->scanning_mount && pData->scanning_mount->fsi )
				{
					ofs = tnprintf( tmpbuf, sizeof( tmpbuf ), WIDE( "%s/%s" ), findbasename( pInfo ), pData->scanning_mount->fsi->find_get_name( findcursor( pInfo ) ) );
				}
				else
				{
#ifdef WIN32
#  ifdef UNDER_CE
					ofs = tnprintf( tmpbuf, sizeof( tmpbuf ), WIDE( "%s/%s" ), findbasename( pInfo ), finddata( pInfo )->cFileName );
#  else
#    ifdef UNICODE
					ofs = snwprintf( tmpbuf, sizeof( tmpbuf ), WIDE( "%s/%s" ), findbasename( pInfo ), finddata( pInfo )->name );
#    else
					ofs = tnprintf( tmpbuf, sizeof( tmpbuf ), WIDE( "%s/%s" ), findbasename( pInfo ), finddata( pInfo )->name );
#    endif
#  endif
#else	
					ofs = tnprintf( tmpbuf, sizeof( tmpbuf ), WIDE( "%s/%s" ), findbasename( pInfo ), de->d_name );
#endif
				}
				//lprintf( "process sub... %s %s", tmpbuf, findmask(pInfo)  );
				processed |= ScanFilesEx( tmpbuf, findmask( pInfo ), (POINTER*)pData, Process, flags, psvUser, TRUE, pData->scanning_mount );
			}
			else
			{
				//lprintf( "process sub..." );
				processed |= ScanFilesEx( pData->buffer, findmask( pInfo ), (POINTER*)pData, Process, flags, psvUser, TRUE, pData->scanning_mount );
			}
		}
		if( !processed )
			goto getnext;
		if( tmp_base )
			Release( tmp_base );
		return (*pInfo) ? 1 : 0;
	}
#ifdef UNICODE
	Deallocate( char *, pDataBuffer );
	}
#else 
#  undef pDataBuffer
#endif
	if( ( sendflags = SFF_DIRECTORY, ( ( flags & SFF_DIRECTORIES )
#ifdef WIN32
#  ifdef UNDER_CE
												 && ( finddata(pInfo)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
#  else
												 && ( finddata(pInfo)->attrib & _A_SUBDIR )
#  endif
#else
												 && ( IsPath( pData->buffer ) )

#endif
												) ) || ( sendflags = 0, CompareMask( findmask( pInfo )
#ifdef WIN32
#  ifdef UNDER_CE
																							  , finddata(pInfo)->cFileName
#  else
																							  , pData->file_buffer
#  endif
#else
																							  , de->d_name
#endif
																								// yes this is silly - but it's correct...
																							  , (flags & SFF_IGNORECASE)?0:0 ) ) )
	{
		//lprintf( "Send %s", pData->buffer );
		if( Process != NULL )
			Process( psvUser, pData->buffer, sendflags );
		if( tmp_base )
			Release( tmp_base );
		return (*pInfo)?1:0;
	}
	if( tmp_base )
		Release( tmp_base );
	return (*pInfo)?1:0;
}