Solved

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

Posted on 1997-06-02
8
554 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Revamp Your Training Process

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action.

 
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
 
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

Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Problem to adjust sheet 1 95
Post a good COM tutorial 1 68
How to LOAD up a .NET Framework website with data? 2 59
Authentication of Web Services 3 98
This tutorial is about how to put some of your C++ program's functionality into a standard DLL, and how to make working with the EXE and the DLL simple and seamless.   We'll be using Microsoft Visual Studio 2008 and we will cut out the noise; that i…
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…
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…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

730 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