Solved

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

Posted on 1997-06-02
8
531 Views
Last Modified: 2013-12-03
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
Comment
Question by:moosach
  • 4
  • 3
8 Comments
 
LVL 1

Author Comment

by:moosach
ID: 1397794
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
 
LVL 15

Accepted Solution

by:
NickRepin earned 100 total points
ID: 1397795
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
 
LVL 15

Expert Comment

by:NickRepin
ID: 1397796
Also, I'm not sure you can pass non-wide-char PortName to AddPortEx. Try also to convert it wide char.
0
 
LVL 1

Author Comment

by:moosach
ID: 1397797
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
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 15

Expert Comment

by:NickRepin
ID: 1397798
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
 
LVL 1

Author Comment

by:moosach
ID: 1397799
You'll get an "A"++ :-) !

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

Regards

Toni
0
 
LVL 2

Expert Comment

by:freter
ID: 4569312
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
 
LVL 15

Expert Comment

by:NickRepin
ID: 4570420
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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

As more and more people are shifting to the latest .Net frameworks, the windows presentation framework is gaining importance by the day. Many people are now turning to WPF controls to provide a rich user experience. I have been using WPF controls fo…
After several hours of googling I could not gather any information on this topic. There are several ways of controlling the USB port connected to any storage device. The best example of that is by changing the registry value of "HKEY_LOCAL_MACHINE\S…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now