Boy, I wish I knew half of what you know.
How in the world do you think of this stuff?
It worked. On to the next part.
Sadly, all I wanted was the printer's port.
Thanks soooo much!!
Boy, I wish I knew half of what you know.
How in the world do you think of this stuff?
It worked. On to the next part.
Sadly, all I wanted was the printer's port.
Thanks soooo much!!
I've got about 5,000 questions, which of course I won't ask.
But - what is the difference between:
I realize that the first is that pi2 is a pointer.Code:PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2)piBuf; //and this: PRINTER_INFO_2 pi2 = (PRINTER_INFO_2 *) piBuf;
How do you know when to use what? A reference would be fine.
Pertaining to a variable (in & out) that equates to an argument:
1. how do you know how to cast it and
2. when/where do you use a pointer?
3. When do you instantiate a variable before you use it as a var? How do you know what to instantiate it as?
Last edited by MAtkins; 06-14-2016 at 12:11 PM.
The main thing is to keep things as simple as possible. Notice how we don't need any casts except to access the struct field in the buffer:
I assume port is freed at some point, somehow. I don't know PHP. I just looked up a little about how PHP extensions read and return values.Code:char *piBuf, *p, *port; DWORD cbBuf = 0; GetPrinter(resource->handle, 2, NULL, 0, &cbBuf); piBuf = emalloc(cbBuf); if (GetPrinter(resource->handle, 2, piBuf, cbBuf, &cbBuf) == 0) RETURN_STRING("GetPrinter failed!", 1); p = ((PRINTER_INFO_2*)piBuf)->pPortName; port = emalloc(strlen(p) + 1); strcpy(port, p); free(piBuf); RETURN_STRING(port, 0);
They're both wrong. It should be:
Code:PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2 *) piBuf;These questions are too general to answer, really.1. how do you know how to cast it and
2. when/where do you use a pointer?
The prime directive is to avoid casting.
Only cast when absolutely necessary since a cast can hide problems.
Thanks
What does this mean?Code:(PRINTER_INFO_2 *) piBuf
Does this work?
The output is supposed to be a string array.
I don't know how to cast/convert it.
Code:LPTSTR *arCapabilities; //this is a pointer in Windows types if(DeviceCapabilities(resource->name, pi2->pPortName, DC_BINNAMES, *arCapabilities, NULL) == 0) { RETURN_STRING("DeviceCapabilities failed"); }
You have to read the documentation for DeviceCapabilities carefully. Each "capability", like DC_BINNAMES, has a different format.
Code:#define BNLEN 24 FILE *fp; DWORD dcRet; char (*pOut)[BNLEN]; // ptr to dynam array of 24-element char arrays // Get number of bin names. dcRet = DeviceCapabilities( resource->name, pi2->pPortName, DC_BINNAMES, NULL, NULL); // or pi2->pDevMode if (dcRet == (DWORD)-1) RETURN_STRING("! DeviceCapabilities 1 failed", 1); // Alloc and fill bin names. pOut = emalloc(dcRet * BNLEN); dcRet = DeviceCapabilities( resource->name, pi2->pPortName, DC_BINNAMES, (LPTSTR)pOut, NULL); // or pi2->pDevMode if (dcRet == (DWORD)-1) RETURN_STRING("! DeviceCapabilities 2 failed", 1); // Write bin names to a file. // Since it's possible for a bin name to be 24 chars long // and in that case to not have a zero-terminator, // copy it to another array to ensure zero-termination. fp = fopen("outfile", "w"); for (DWORD i = 0; i < dcRet; i++) { char s[BNLEN+1] = {0}; strncpy(s, pOut[i], BINLEN); fprintf(fp, "%s\n", s); } fclose(fp); free(pOut); RETURN_STRING("Success", 1);
Thanks again for your patience.
I did read the info about BINNAMES but don't know how to make a string array and wasn't sure what to put into that param.
I haven't tried your code yet but I've got some questions:
1. I've got conflicting info on the return value. The one in BINNAMES says number of bins, the output below the Capabilities says number of bytes.
How do you know which it is?
2. Why did you cast a char into a LPTSTR instead of defining it as such?
3. What do you mean by a 'dynamic array'; that we can alter it at run time? or - that DeviceCapabilities can alter or it? - or . . .
What in the code makes the array dynamic?
4. What do the parens mean in the line:or any variable or argument name or cast?Code:char (*pOut)[BNLEN];
5. It looks like you expect a single char of the length (BNLEN * 24).
It says "The pOutput buffer receives an array of string buffers. Each string buffer is 24 characters long". The phrase, 'array of string buffers' seems to indicate to me an array of arrays of chars.
If that's what we sent them, why don't they return an array of 24 byte char arrays?
Well, I thought I was getting somewhere.
I still can't get the port name.
From above, this works if I replace sprintf with just a value in RETURN_STRING.
If I use sprintf to try to access pi2->pPortName I get an HTTP 500 error.
I don't know how to verify what pi2 ends up being.
Also, what do the parens mean in the line:
Code:PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2 *)piBuf;Code:if (GetPrinter(resource->handle, 2, piBuf, cbBuf, &cbBuf) == 0) { RETURN_STRING("GetPrinter failed!", 1); } PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2 *)piBuf; //sprintf(sRtn, "PortName: %s", pi2->pPortName); RETURN_STRING("Got Printer");
Try this. What are the contents of "error.txt" after you run it?
Code:FILE *fp; PRINTER_INFO_2 *pi2; DWORD cbBuf = 0; fp=fopen("C:\\php-dev\\CExamples\\printer7\\error.txt", "w"); GetPrinter(resource->handle, 2, NULL, 0, &cbBuf); fprintf(fp, "cbBuf: %u\n", (unsigned)cbBuf); pi2 = emalloc(cbBuf); if (GetPrinter(resource->handle, 2, (LPBYTE)pi2, cbBuf, &cbBuf) == 0) { fprintf(fp, "Error: %u\n", GetLastError()); fclose(fp); RETURN_STRING("GetPrinter failed!", 1); } fprintf(fp, "GetPrinter succeeded\n"); fprintf(fp, "Port: %s\n", pi2->pPortName); fclose(fp); free(pi2); RETURN_STRING("got printer info", 1);
I get an HTTP 500 error.
I've attached the file & the header.
This returned an HTTP 500 error too:
Code:if (GetPrinter(resource->handle, 2, (LPBYTE)pi2, cbBuf, &cbBuf) == 0) { fprintf(fp, "Error: %u\n", GetLastError()); fclose(fp); RETURN_STRING("GetPrinter failed!", 1); }
This is strange. I tested it again. It returned an HTTP 500 error.
But - here is what was in the file:
cbBuf: 2008
GetPrinter succeeded
Port: USB001
I don't know why it crashes after it successfully wrote the port name to the file. We should be testing if the fopen call succeeded, but if it wrote to the file then it must have.
Code:fp=fopen("C:\\php-dev\\CExamples\\printer7\\error.txt", "w"); if (fp == NULL) RETURN_STRING("Cannot open error.txt for writing", 1);
This much worked.
I kept working with it & compiling it with more & more code.
This works. I had to remove the free(pi2) and that stopped the HTTP 500 error.
So, I think we're finally on to the next step, getting the printer's paper sources (feeders).
Code:FILE *fp; PRINTER_INFO_2 *pi2Buf; PRINTER_INFO_2 *pi2; DWORD cbBuf = 0; fp=fopen("C:\\php-dev\\CExamples\\printer7\\output.txt", "w"); fprintf(fp, "GetPrinter initiated\n."); GetPrinter(resource->handle, 2, NULL, 0, &cbBuf); fprintf(fp, "cbBuf: %u\n", (unsigned)cbBuf); pi2Buf = emalloc(cbBuf); if (GetPrinter(resource->handle, 2, (LPBYTE)pi2Buf, cbBuf, &cbBuf) == 0) { fprintf(fp, "Error: %u\n", GetLastError()); fclose(fp); RETURN_STRING("GetPrinter failed!", 1); } pi2 = (PRINTER_INFO_2 *)pi2Buf; fprintf(fp, "GetPrinter succeeded\n"); fprintf(fp, "Port: %s\n", pi2->pPortName); fclose(fp);