DEVNAMES Structure

How do you change the members of the DEVNAMES struct.  If I have HP Laser Jet as the printer name, winspool as the driver and Ne02: as the port, how would I place these into wDeviceOffset, wDriverOffset and wOutputOffset of the DEVNAMES Struct?  If you could give me an example, I'd appreciate it.  Thanks.
paulcaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

nietodCommented:
char *Driver = ???;
char *Device = ???;
char *Output = ???

int DriverLen = strlen(Driver);
int DeviceLen = strilen(Device);
int OutputLen = strlen(OPutput);

int AloLen = sizeof(DEVNAMES + DriverLen + Dervice:en + OutputLen + 3;
// the +3 is for the 3 string terminators.

continues.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
nietodCommented:
HGLOBAL DevNamHnd = GlobalAloc(GMEM_MOVABLE,AloLen);

DEVNAMES DevNamPtr = (DEVNAMES *) GlobalLock(DevNamHnd))

DevNamPtr->wDriverOffset = sizeof(DEVNAMES);
DevNamPtr->wDeviceOffset = DevNamPtr->wDriverOffset + DriverLen;
DevNamPtr->wOutputOffset = DevNamPtr->wDeviceOffset + DeviceLen;

continues.
0
nietodCommented:
char *BytPtr = (char *) DevNamPtr;

strcpy(BytPtr + DevNamPtr->wDriverOffset,Driver);
strcpy(BytPtr + DevNamPtr->wDeviceOffset,Device);
strcpy(BytPtr + DevNamPtr->wOutputOffset,Output);

In english.  You calcualt ethe total size of the block of memory to hold the DEVNAMES structure.  This isthe size of the DEVNAMES structure itself, with is really used as a header to this entire block.  Then add on the length of the three strings, including the length required for their terminators.

Then you allocate memory for this block usig GlobalAlloc() and lock the block to get a pointer to it.  Then you fill in the DEVNAMES structure that appears at the start of the block.  The 1st string appears right after the DEVNAMES structure, so the offset to the first string is the sizeof the DEVNAMES structure.  The 2nd string appears right after the first, so its offset is the offset of the first string plus the length of the 1st string, plus 1 for the terminator (WHICH IF FORGOT ABOVE)  And the same for the 3rd string.  

So the code to set the offset should be

DevNamPtr->wDriverOffset = sizeof(DEVNAMES);
DevNamPtr->wDeviceOffset = DevNamPtr->wDriverOffset + DriverLen + 1;
DevNamPtr->wOutputOffset = DevNamPtr->wDeviceOffset + DeviceLen + 1;
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

paulcaAuthor Commented:
I am using Visual C++ 4.2 and GlobalAloc is giving me an error.  Does this have something to do with the version I am using?  The error it gave me was:

error C2065: 'GlobalAloc' : undeclared identifier
0
nietodCommented:
Opps.  try GlobalAlloc()--two l's
0
paulcaAuthor Commented:
Do I have to do something like this once I have implemented the above code?

printDlg->m_pd.hDevNames = BytPtr;
0
nietodCommented:
Sort of.  The global block must be unlocked (GlobalUnlock()) and after you are done with the memory, you must free the global block (GlobalFree().)

And yes, the PRINTDLG's hDevNames should be set to this block, but to the HANDLE for the block, not the pointer to it.  This is mostly for legacy reasons, but the print dialog expects a global handle that it will then lock in order to access the data stored in the memory.
0
paulcaAuthor Commented:
Does this look right?

GlobalUnlock(DevNameHnd);
GlobalFree(DevNameHnd);
printDlg->m_pd.hDevNames = DevNameHnd;
0
nietodCommented:
No.  

GlobalUnlock(DevNameHnd);
printDlg->m_pd.hDevNames = DevNameHnd;
Display the dialog;
use the PRINTDLG to set up the print.
GlobalFree(DevNameHnd);

GlobaAlloc() is like C's new or malloc().  It allocates memory.  However it doesn't return a pointer to the memory.  This is because the memory is movable (or was in 16 bit).  So the OS could move the memory about to keep the heap efficiently organized.  So instead GlobalAlloc returned a handle that refers to the memory, but is not a pointer to it.  In order to get a pointer to the memory, you have to lock it, so it can't be moved about while you use the pointer.  Then when you are done using the memory (at least for a little while) you unlock the memory, this lets the OS move it around again, if needed.  Finally when you are totaly done with the memory, you call GlobalFree(), which deletes the memory, like C++'s delete or free().

the PRINTDLG structure needs to have a handle to this movable block of memory because it will lock the handle, getting a pointer to what you've specified and use this information.  Furthermore, depending on what the  user chooses, the print dialog may free this memory and allocate new memory for the information it returns.  Sot he lock you specify might not be the one you get back, which is another reason why this can't be a pointer.  (Not all pointers point to memory that can be freed, but all HGLOBALS do.)

Also when you are done setting up the print you must rememober to free this device names memory, as shown about AND the device mode block in hDevMode.  This is ALWAYS TRUE, even if you don't allocate these.  i.e. if you set these to NULL they will be returned non-NULL and must be GlobalFree()ed.
0
paulcaAuthor Commented:
Thanks for your time.  You have been a great help.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.