[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 579
  • Last Modified:

How to add a printer port on NT non-interactivly?

Hi everybody,

this is my first question here.

I have a problem on NT 4.0 :

I want to add a printer port without poping up the dialog box of AddPort and without a reboot. Just like the AddPort but without user interactions. The user should not realize that a port is installed.

I found a call AddPortEx in DDK, but not in the Win32 SDK. Nevertheless I tried but the call never returns. To be honest : as expected ...

Now my question : Does anybody know how to use this call (prerequesites) or maybe a better way to install a printer port non-interactivly ?

Any help is appreciated

Regards

Toni
0
moosach
Asked:
moosach
  • 4
  • 3
1 Solution
 
moosachAuthor Commented:
Code Fragment from my unsuccessful trials :

Calling AddPortEx of the localmon.dll doesn’t work. The function doesn’t return after calling.
The same happens with AddPort of the localmon.dll. In this case the AddPort dialog box appears, but after entering the port name and leaving with OK, the function doesn’t return either.

How can this problem be solved?

Code fragment:

MultiByteToWideChar(CP_ACP, 0, "Local Port",-1,MonitorNameW,sizeof(MonitorNameW));
      
lstrcpy(PortName,"c:\\tmp\\testport.prn");

hLib=::LoadLibrary("localmon.dll");

if(!hLib)
{
      ::MessageBox(NULL,"LoadLibrary of localmon.dll failed","TEST",MB_OK);
}


lpfn=(LPFNDLLFUNC1)GetProcAddress(hLib,"InitializePrintMonitor");

MultiByteToWideChar(CP_ACP,
                  0,
                           
"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors\\Local Port",
                  -1,
                  RegRootPrMonitorW,
                  sizeof(RegRootPrMonitorW));

lpMonitorEx =lpfn((LPWSTR)RegRootPrMonitorW );

if(lpMonitorEx)
{
      if( (lpMonitorEx->Monitor.pfnAddPortEx)(NULL,1,(LPBYTE)PortName,(LPWSTR)MonitorNameW))      
      {
            ::MessageBox( NULL,"AddPortEx() passed","TEST",MB_OK );
      }
      else
      {
            ::MessageBox( NULL,"AddPortEx() failed","TEST",MB_OK );
      }
}
                        
::FreeLibrary(hLib);


0
 
NickRepinCommented:
You must pass pointer to PORT_INFO_1 structure as third parameter for AddPortEx.

Here is PORT_INFO_1 declaration:

typedef struct _PORT_INFO_1 { // pi1
    LPTSTR pName;
} PORT_INFO_1;

That is, you must pass pointer-to-pointer to port name.

Instead, you pass pointer to port name. Try to use (LPBYTE) &PortName.


0
 
NickRepinCommented:
Also, I'm not sure you can pass non-wide-char PortName to AddPortEx. Try also to convert it wide char.
0
Nothing ever in the clear!

This technical paper will help you implement VMware’s VM encryption as well as implement Veeam encryption which together will achieve the nothing ever in the clear goal. If a bad guy steals VMs, backups or traffic they get nothing.

 
moosachAuthor Commented:
Hi,

thanks a lot for answering my question !

Unfortunately your advice doesn't solve my problem. I changed
my code following your mail, but still the DDK function AddPortEx doesn't return. The same is true for the AddPort from DDK. This one comes with the popup for entering the port and then it doesn't return either.

The AddPort from SDK works as expected, but I don't want to have this popup. That is my problem ...

Do I miss something ? Is there a different way to solve my problem ?

Any help is appreciated.

Regards

Toni
0
 
NickRepinCommented:
You choosed a wrong way at all. You should not call to InitializePrintMonitor, because this function must reside in print monitor and must be called by spooler internally.

Instead, you should call to undocumented AddPortEx of winspool.exe.

Here is a test program which adds port "Nick Port".

If you will be satisfied with my answer, please give me grade 'A', because now I should write another program to delete this port from my PC. ;)

#include <windows.h>
#include <iostream.h>

extern "C" __import BOOL WINAPI AddPortExA(LPSTR pName, DWORD level,  LPBYTE buffer, LPSTR monitorName);

void main(void)
{
   BOOL r;

   // Print currently installed ports
   DWORD nNeed,nRet;
   PORT_INFO_1 pi[200];
   r=EnumPorts(NULL,1,LPBYTE(&pi[0]),sizeof(pi),&nNeed,&nRet);
   cout<<"EnumPorts()="<<r<<" nRet="<<nRet<<endl;
   if(!r || nRet<1)
      return;
   for(int i=0;i<nRet;i++)
      cout<<"Port name "<<i<<": "<<(pi[i].pName)<<endl;

   // Enum monitors to retrieve monitor name
   MONITOR_INFO_1 mi[100];
   r=EnumMonitors(NULL,1,LPBYTE(&mi[0]),sizeof(mi),&nNeed,&nRet);
   cout<<"EnumMonitors()="<<r<<" nRet="<<nRet<<endl;
   if(!r || nRet<1)
      return;
   cout<<"Monitor name 0: "<<(mi[0].pName)<<endl;

   // Create new port
   CHAR PortName[200]="Nick Port"; //"c:\\tmp\\testport.prn";
   pi[0].pName=&PortName[0];
   r=AddPortExA(NULL,1,LPBYTE(&pi[0]),mi[0].pName);
   cout<<"AddPortExA "<<(r ? "OK" : "failed")<<endl;

   // List port names again
   r=EnumPorts(NULL,1,LPBYTE(&pi[0]),sizeof(pi),&nNeed,&nRet);
   cout<<"EnumPorts()="<<r<<" nRet="<<nRet<<endl;
   if(!r || nRet<1)
      return;
   for(int i=0;i<nRet;i++)
      cout<<"Port name "<<i<<": "<<(pi[i].pName)<<endl;
}

0
 
moosachAuthor Commented:
You'll get an "A"++ :-) !

Thanks a lot for your help !! You are really an expert !!!

Regards

Toni
0
 
freterCommented:
Hi,

I am currently trying to add LPR ports using the technique depicted above (using the undocumented AdPortEx function), but I can't seem to succeed. I checked the lprmon.dll and found that it doesn't export a function AddPortEx. Might this be the cause for my problem?
OBTW: when adding local ports or PDF ports (I've got Acrobat installed), everything's fine...

TIA,
</freter>
0
 
NickRepinCommented:
AddPortEx is in WINSPOOL.DRV

#include <windows.h>
#include <iostream.h>

typedef BOOL (WINAPI *AddPortExAT)(LPSTR pName,DWORD level,
   LPBYTE buffer,LPSTR monitorName);

AddPortExAT pf;

void main(void)
{
   int i;
   BOOL r;

   HINSTANCE hLib=LoadLibrary("WINSPOOL.DRV");
   pf=(AddPortExAT)GetProcAddress(hLib,"AddPortExA");
   if(!pf) {
      cout<<"Unable to find AddPortExA"<<endl;
      return;
   }


   // Print currently installed ports
   DWORD nNeed,nRet;
   PORT_INFO_1 pi[200];
   r=EnumPorts(NULL,1,PBYTE(pi),sizeof(pi),&nNeed,&nRet);
   cout<<"EnumPorts()="<<r<<" nRet="<<nRet<<endl;
   if(!r || nRet<1) {
      cout<<"No ports found"<<endl;
      return;
   }
   for(i=0;i<nRet;i++)
      cout<<"Port name "<<i<<": "<<(pi[i].pName)<<endl;

   // Enum monitors to retrieve monitor name
   MONITOR_INFO_1 mi[100];
   r=EnumMonitors(NULL,1,PBYTE(mi),sizeof(mi),&nNeed,&nRet);
   cout<<"EnumMonitors()="<<r<<" nRet="<<nRet<<endl;
   if(!r || nRet<1) {
      cout<<"No monitors found"<<endl;
      return;
   }
   cout<<"Monitor #0: "<<(mi[0].pName)<<endl;

   // Create new port
   pi[0].pName="TestPort1:";
   r=pf(NULL,1,PBYTE(pi),/*mi[1].pName*/"Local Port");
   cout<<"AddPortExA "<<(r ? "OK" : "failed")<<endl;
   if(!r) cout<<"err="<<GetLastError()<<endl;

   // List port names again
   r=EnumPorts(NULL,1,PBYTE(pi),sizeof(pi),&nNeed,&nRet);
   cout<<"EnumPorts()="<<r<<" nRet="<<nRet<<endl;
   if(!r || nRet<1)
      return;
   for(i=0;i<nRet;i++)
      cout<<"Port name "<<i<<": "<<(pi[i].pName)<<endl;
}
0

Featured Post

Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now