Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

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

Posted on 1997-06-02
8
Medium Priority
?
576 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 400 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
 [eBook] Windows Nano Server

Download this FREE eBook and learn all you need to get started with Windows Nano Server, including deployment options, remote management
and troubleshooting tips and tricks

 
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

Ask an Anonymous Question!

Don't feel intimidated by what you don't know. Ask your question anonymously. It's easy! Learn more and upgrade.

Question has a verified solution.

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

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…
For a while now I'v been searching for a circular progress control, much like the one you get when first starting your Silverlight application. I found a couple that were written in WPF and there were a few written in Silverlight, but all appeared o…
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…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…

610 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