VMware Horizon Community
cernerguy
Contributor
Contributor
Jump to solution

How to get a list of all named pipes in a ThinApp

I have a simple program to list all the files of a folder.  I use it to get a list of named pipes by passing
\\.\pipe\* as the argument but it does not work if I package the program as a thin app.  I am getting error code 3 (ERROR_PATH_NOT_FOUND).  I've tried using CreateFile on
\\.\pipe\ but it also failed when running as a ThinApp. Are their ways to get a list of all named pipes within a ThinApp?  Here is the source code.

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

#include "stdafx.h"

int main(int argc, char* argv[])
{
   WIN32_FIND_DATA FindFileData;
   HANDLE hFind;

   if( argc != 2 )
   {
          _tprintf(TEXT("Usage: %s [target_file]\n"), argv[0]);
          return -1;
   }

   _tprintf (TEXT("Target file is %s\n"), argv[1]);

   hFind = FindFirstFile(argv[1], &FindFileData);
   if (hFind == INVALID_HANDLE_VALUE) 
   {
          printf ("FindFirstFile failed (%d)\n", GetLastError());
          return -1;
   } 
   else 
   {
          _tprintf (TEXT("The first file found is %s\n"), 
               FindFileData.cFileName);

          BOOL nextFile = FindNextFile(hFind, &FindFileData);

          while (nextFile)
          {
               _tprintf (TEXT("The next file found is %s\n"), 
                         FindFileData.cFileName);

               nextFile = FindNextFile(hFind, &FindFileData);
          }

          FindClose(hFind);
   }

   return 0;
}
Tags (2)
Reply
0 Kudos
1 Solution

Accepted Solutions
Pankaj11
Hot Shot
Hot Shot
Jump to solution

Ok, so regarding the original FindFirstFile example, if I try it with 4.6 it does work for me. I am using VC 6 to create the application and then adding it to the cmd project and then rebuilding. I have tried these combinations:

app.exe \\.\pipe\*  (this works)

app.exe \\.\pipe\   (this doesn't work, natively too it doesn't work)

app.exe //./pipe/*  (this works)

app.exe //./pipe/   (this doesn't work, natively too it doesn't work)

can you tell me about the results you get when you try the above?

Thanks.

View solution in original post

Reply
0 Kudos
11 Replies
Pankaj11
Hot Shot
Hot Shot
Jump to solution

Hi cernerguy,

I ThinApped your application with ThinApp 4.6 and the pipe enumeration worked fine. What I basically did is:

- just add the executable created using your code sample to the %Desktop% folder to an empty (which had just cmd.exe, regedit.exe and iexplore.exe as the entry points) ThinApp project,

- then rebuild with 4.6, launch cmd.exe entry point

- and then browse to the desktop folder and launch the pipe enumeration application.

I could see the pipes enumerated.

Which ThinApp version are you using?

Thanks.

Reply
0 Kudos
Pankaj11
Hot Shot
Hot Shot
Jump to solution

With ThinApp 4.5 I can repro the issue that you are facing, but with 4.6 and later it seems fixed.

Thanks.

cernerguy
Contributor
Contributor
Jump to solution

Hi Pankaj1,

I am using ThinApp 4.6 and the same entry point as you are. I’ve found that CreateFile will work if I pass it “//./pipe/”. With the handle, I was able to use NtQueryDirectoryFile to get a list of named pipes. I’ve tried passing //./pipe/* but it still does not work. Are you compiling the program using VC6?

-Binh

Reply
0 Kudos
Pankaj11
Hot Shot
Hot Shot
Jump to solution

Hi Binh,

So, you are not using the FindFirstFile code sample that you have pasted in your initial posting and using CreateFile and NtQueryDirectoryFile apis to get the list of pipes? Can you please upload this new code and I can test at my end?

Also, just to confirm, in cmd.exe when you type "yourapp.exe //./pipe/" it works and "yourapp.exe \\.\pipe\*" doesn't work, right?

Thanks.

Reply
0 Kudos
cernerguy
Contributor
Contributor
Jump to solution

I’ve was not able to get my sample code to work. Both “yourapp.exe //./pipe/” and “yourapp.exe
.\pipe\
<file:///
.\pipe\*>” will fail.

I use another program where it uses CreateFile and NtQueryDirectoryFile to list the named pipes. The code is very simpler to the example provided here . This example will run if you use “//./pipe/” instead of “

.
Pipe\”.

http://stackoverflow.com/questions/481759/enumerating-named-pipes-in-windows

Reply
0 Kudos
Pankaj11
Hot Shot
Hot Shot
Jump to solution

Yeah, if I try the sample from the page http://stackoverflow.com/questions/481759/enumerating-named-pipes-in-windows, then it works natively, but doesn't work with ThinApp 4.6. But, if I try the latest ThinApp 4.6.1 build (this is internal build, 4.6.1 is not yet released), then it works, so I guess it is fixed in the code now and once 4.6.1 is out, you can test it.

Thanks.

Reply
0 Kudos
cernerguy
Contributor
Contributor
Jump to solution

You mentioned that my sample code worked for you using ThinApp 4.6. Was it actually 4.6.1 or should it work for me as well using the released version of 4.6?

Reply
0 Kudos
Pankaj11
Hot Shot
Hot Shot
Jump to solution

What I meant was that the code present at this page http://stackoverflow.com/questions/481759/enumerating-named-pipes-in-windows

// pipelist.cpp (Windows NT/2000)   
//   
// This example will show how you can enumerate all named pipes   
// active on a system.   
//   
// (c)2000 Ashot Oganesyan K, SmartLine, Inc   
// mailto:ashot@aha.ru, http://www.protect-me.com, http://www.codepile.com   

#include <windows.h>   
#include <stdio.h>  

#define FileDirectoryInformation 1   
#define STATUS_NO_MORE_FILES 0x80000006L   

typedef struct   
{   
    USHORT Length;   
    USHORT MaximumLength;   
    PWSTR  Buffer;   
} UNICODE_STRING, *PUNICODE_STRING;   

typedef struct   
{   
    LONG Status;   
    ULONG Information;   
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;   

typedef struct {   
    ULONG NextEntryOffset;   
    ULONG FileIndex;   
    LARGE_INTEGER CreationTime;   
    LARGE_INTEGER LastAccessTime;   
    LARGE_INTEGER LastWriteTime;   
    LARGE_INTEGER ChangeTime;   
    LARGE_INTEGER EndOfFile;   
    LARGE_INTEGER AllocationSize;   
    ULONG FileAttributes;   
    ULONG FileNameLength;   
    union {   
        struct {   
            WCHAR FileName[1];   
        } FileDirectoryInformationClass;   

        struct {   
            DWORD dwUknown1;   
            WCHAR FileName[1];   
        } FileFullDirectoryInformationClass;   

        struct {   
            DWORD dwUknown2;   
            USHORT AltFileNameLen;   
            WCHAR AltFileName[12];   
            WCHAR FileName[1];   
    } FileBothDirectoryInformationClass;   
    };   
} FILE_QUERY_DIRECTORY, *PFILE_QUERY_DIRECTORY;   


// ntdll!NtQueryDirectoryFile (NT specific!)   
//   
// The function searches a directory for a file whose name and attributes   
// match those specified in the function call.   
//   
// NTSYSAPI   
// NTSTATUS   
// NTAPI   
// NtQueryDirectoryFile(   
//    IN HANDLE FileHandle,                      // handle to the file   
//    IN HANDLE EventHandle OPTIONAL,   
//    IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,   
//    IN PVOID ApcContext OPTIONAL,   
//    OUT PIO_STATUS_BLOCK IoStatusBlock,   
//    OUT PVOID Buffer,                          // pointer to the buffer to receive the result   
//    IN ULONG BufferLength,                     // length of Buffer   
//    IN FILE_INFORMATION_CLASS InformationClass,// information type   
//    IN BOOLEAN ReturnByOne,                    // each call returns info for only one file   
//    IN PUNICODE_STRING FileTemplate OPTIONAL,  // template for search   
//    IN BOOLEAN Reset                           // restart search   
// );   
typedef LONG (WINAPI *PROCNTQDF)( HANDLE,HANDLE,PVOID,PVOID,PIO_STATUS_BLOCK,PVOID,ULONG,   
                                  UINT,BOOL,PUNICODE_STRING,BOOL );   

PROCNTQDF NtQueryDirectoryFile;   

void main(void)   
{   
    LONG ntStatus;   
    IO_STATUS_BLOCK IoStatus;   
    HANDLE hPipe;   
    BOOL bReset = TRUE;   
    PFILE_QUERY_DIRECTORY DirInfo,   
                          TmpInfo;   


    NtQueryDirectoryFile = (PROCNTQDF)GetProcAddress(   
                                      GetModuleHandle("ntdll"),   
                                      "NtQueryDirectoryFile"   
                                      );   

    if (!NtQueryDirectoryFile)   
       return;   

    hPipe = CreateFile("\\\\.\\Pipe\\",GENERIC_READ,   
                       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,   
                       NULL,OPEN_EXISTING,0,NULL);   

   if(hPipe == INVALID_HANDLE_VALUE)   
     return;   

   DirInfo = (PFILE_QUERY_DIRECTORY) new BYTE[1024];   

   printf("Pipe name (Number of instances, Maximum instances)\n\n");   
   while(1)   
   {   
       ntStatus = NtQueryDirectoryFile(hPipe,NULL,NULL,NULL,&IoStatus,DirInfo,1024,   
                                       FileDirectoryInformation,FALSE,NULL,bReset);   

       if (ntStatus!=NO_ERROR)   
       {   
          if (ntStatus == STATUS_NO_MORE_FILES)   
             break;   

          return;   
       }   

       TmpInfo = DirInfo;   
       while(1)   
       {
          // Store old values before we mangle the buffer
          const int endStringAt = TmpInfo->FileNameLength/sizeof(WCHAR);
          const WCHAR oldValue = TmpInfo->FileDirectoryInformationClass.FileName[endStringAt];

          // Place a null character at the end of the string so wprintf doesn't read past the end
          TmpInfo->FileDirectoryInformationClass.FileName[endStringAt] = NULL;   

          wprintf(L"%s (%d, %d)\n",TmpInfo->FileDirectoryInformationClass.FileName,   
                                   TmpInfo->EndOfFile.LowPart,   
                                   TmpInfo->AllocationSize.LowPart );   

          // Restore the buffer to its correct state
          TmpInfo->FileDirectoryInformationClass.FileName[endStringAt] = oldValue;

          if(TmpInfo->NextEntryOffset==0)   
            break;   

          TmpInfo = (PFILE_QUERY_DIRECTORY)((DWORD)TmpInfo+TmpInfo->NextEntryOffset);   
       }   

       bReset = FALSE;   
   }   

   delete DirInfo;   
   CloseHandle(hPipe);   
}   
if I use this code, and add it(the visual studio application created out of it) to the cmd.exe project, rebuild with ThinApp 4.6, launch the application from virtual cmd.exe then it doesn't work, but if I rebuild the cmd project with ThinApp 4.6.1 then it works. So with the released 4.6 that you have, you won't be able to run it but once 4.6.1 is released using that you should be able to run it well.
Reply
0 Kudos
cernerguy
Contributor
Contributor
Jump to solution

Yes, I understand but I was curious about the original example using FindFirstFile where you mentioned it worked for 4.6 and later. I haven’t gotten it to work in my setup. Was there anything that I could look into?

Reply
0 Kudos
Pankaj11
Hot Shot
Hot Shot
Jump to solution

Ok, so regarding the original FindFirstFile example, if I try it with 4.6 it does work for me. I am using VC 6 to create the application and then adding it to the cmd project and then rebuilding. I have tried these combinations:

app.exe \\.\pipe\*  (this works)

app.exe \\.\pipe\   (this doesn't work, natively too it doesn't work)

app.exe //./pipe/*  (this works)

app.exe //./pipe/   (this doesn't work, natively too it doesn't work)

can you tell me about the results you get when you try the above?

Thanks.

Reply
0 Kudos
cernerguy
Contributor
Contributor
Jump to solution

I repeated the test and it now works for both app.exe
.\pipe\*<file:///
.\pipe\*> and app.exe //./pipe/* . I’ve rebuild the environment using 4.6. I may need to look back on the original test.

Reply
0 Kudos