@luckykiet/node-printer 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog +36 -0
- package/Gruntfile.js +75 -0
- package/README.md +61 -0
- package/binding.gyp +77 -0
- package/examples/cancelJob.js +34 -0
- package/examples/example_zebra_printer.js +15 -0
- package/examples/getDefaultPrinterName.js +4 -0
- package/examples/getPrinterDriverOptions.js +9 -0
- package/examples/getPrinters.js +3 -0
- package/examples/getSupportedFormats.js +3 -0
- package/examples/getSupportedJobCommands.js +3 -0
- package/examples/printFile.js +30 -0
- package/examples/printPDFFileInBuffer.js +37 -0
- package/examples/printPDFInWindows.js +52 -0
- package/examples/print_raw.js +10 -0
- package/examples/test.pdf +0 -0
- package/lib/index.js +1 -0
- package/lib/node_printer.node +0 -0
- package/lib/printer.js +330 -0
- package/package.json +48 -0
- package/printer.js +1 -0
- package/src/macros.hh +159 -0
- package/src/node_printer.cc +41 -0
- package/src/node_printer.hpp +123 -0
- package/src/node_printer_posix.cc +530 -0
- package/src/node_printer_win.cc +750 -0
- package/test/getPrinters.js +14 -0
- package/tools/buildElectronLinux.sh +10 -0
- package/tools/buildElectronWindows.ps1 +20 -0
- package/tools/buildWindows.ps1 +23 -0
- package/tools/generateReleaseBuildsLinux.sh +59 -0
- package/tools/generateReleaseBuildsWindows.ps1 +63 -0
- package/tools/getSourceFiles.py +12 -0
- package/tsconfig.json +22 -0
- package/types/index.d.ts +57 -0
|
@@ -0,0 +1,750 @@
|
|
|
1
|
+
#include "node_printer.hpp"
|
|
2
|
+
|
|
3
|
+
#if _MSC_VER
|
|
4
|
+
#include <windows.h>
|
|
5
|
+
#include <Winspool.h>
|
|
6
|
+
#include <Wingdi.h>
|
|
7
|
+
#pragma comment(lib, "Winspool.lib")
|
|
8
|
+
#else
|
|
9
|
+
#error "Unsupported compiler for windows. Feel free to add it."
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
#include <string>
|
|
13
|
+
#include <map>
|
|
14
|
+
#include <utility>
|
|
15
|
+
#include <sstream>
|
|
16
|
+
#include <node_version.h>
|
|
17
|
+
|
|
18
|
+
namespace{
|
|
19
|
+
typedef std::map<std::string, DWORD> StatusMapType;
|
|
20
|
+
|
|
21
|
+
/** Memory value class management to avoid memory leak
|
|
22
|
+
*/
|
|
23
|
+
template<typename Type>
|
|
24
|
+
class MemValue: public MemValueBase<Type> {
|
|
25
|
+
public:
|
|
26
|
+
/** Constructor of allocating iSizeKbytes bytes memory;
|
|
27
|
+
* @param iSizeKbytes size in bytes of required allocating memory
|
|
28
|
+
*/
|
|
29
|
+
MemValue(const DWORD iSizeKbytes) {
|
|
30
|
+
_value = (Type*)malloc(iSizeKbytes);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
~MemValue () {
|
|
34
|
+
free();
|
|
35
|
+
}
|
|
36
|
+
protected:
|
|
37
|
+
virtual void free() {
|
|
38
|
+
if(_value != NULL)
|
|
39
|
+
{
|
|
40
|
+
::free(_value);
|
|
41
|
+
_value = NULL;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
struct PrinterHandle
|
|
47
|
+
{
|
|
48
|
+
PrinterHandle(LPWSTR iPrinterName)
|
|
49
|
+
{
|
|
50
|
+
_ok = OpenPrinterW(iPrinterName, &_printer, NULL);
|
|
51
|
+
}
|
|
52
|
+
~PrinterHandle()
|
|
53
|
+
{
|
|
54
|
+
if(_ok)
|
|
55
|
+
{
|
|
56
|
+
ClosePrinter(_printer);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
operator HANDLE() {return _printer;}
|
|
60
|
+
operator bool() { return (!!_ok);}
|
|
61
|
+
HANDLE & operator *() { return _printer;}
|
|
62
|
+
HANDLE * operator ->() { return &_printer;}
|
|
63
|
+
const HANDLE & operator ->() const { return _printer;}
|
|
64
|
+
HANDLE _printer;
|
|
65
|
+
BOOL _ok;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const StatusMapType& getStatusMap()
|
|
69
|
+
{
|
|
70
|
+
static StatusMapType result;
|
|
71
|
+
if(!result.empty())
|
|
72
|
+
{
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
// add only first time
|
|
76
|
+
#define STATUS_PRINTER_ADD(value, type) result.insert(std::make_pair(value, type))
|
|
77
|
+
STATUS_PRINTER_ADD("BUSY", PRINTER_STATUS_BUSY);
|
|
78
|
+
STATUS_PRINTER_ADD("DOOR-OPEN", PRINTER_STATUS_DOOR_OPEN);
|
|
79
|
+
STATUS_PRINTER_ADD("ERROR", PRINTER_STATUS_ERROR);
|
|
80
|
+
STATUS_PRINTER_ADD("INITIALIZING", PRINTER_STATUS_INITIALIZING);
|
|
81
|
+
STATUS_PRINTER_ADD("IO-ACTIVE", PRINTER_STATUS_IO_ACTIVE);
|
|
82
|
+
STATUS_PRINTER_ADD("MANUAL-FEED", PRINTER_STATUS_MANUAL_FEED);
|
|
83
|
+
STATUS_PRINTER_ADD("NO-TONER", PRINTER_STATUS_NO_TONER);
|
|
84
|
+
STATUS_PRINTER_ADD("NOT-AVAILABLE", PRINTER_STATUS_NOT_AVAILABLE);
|
|
85
|
+
STATUS_PRINTER_ADD("OFFLINE", PRINTER_STATUS_OFFLINE);
|
|
86
|
+
STATUS_PRINTER_ADD("OUT-OF-MEMORY", PRINTER_STATUS_OUT_OF_MEMORY);
|
|
87
|
+
STATUS_PRINTER_ADD("OUTPUT-BIN-FULL", PRINTER_STATUS_OUTPUT_BIN_FULL);
|
|
88
|
+
STATUS_PRINTER_ADD("PAGE-PUNT", PRINTER_STATUS_PAGE_PUNT);
|
|
89
|
+
STATUS_PRINTER_ADD("PAPER-JAM", PRINTER_STATUS_PAPER_JAM);
|
|
90
|
+
STATUS_PRINTER_ADD("PAPER-OUT", PRINTER_STATUS_PAPER_OUT);
|
|
91
|
+
STATUS_PRINTER_ADD("PAPER-PROBLEM", PRINTER_STATUS_PAPER_PROBLEM);
|
|
92
|
+
STATUS_PRINTER_ADD("PAUSED", PRINTER_STATUS_PAUSED);
|
|
93
|
+
STATUS_PRINTER_ADD("PENDING-DELETION", PRINTER_STATUS_PENDING_DELETION);
|
|
94
|
+
STATUS_PRINTER_ADD("POWER-SAVE", PRINTER_STATUS_POWER_SAVE);
|
|
95
|
+
STATUS_PRINTER_ADD("PRINTING", PRINTER_STATUS_PRINTING);
|
|
96
|
+
STATUS_PRINTER_ADD("PROCESSING", PRINTER_STATUS_PROCESSING);
|
|
97
|
+
STATUS_PRINTER_ADD("SERVER-UNKNOWN", PRINTER_STATUS_SERVER_UNKNOWN);
|
|
98
|
+
STATUS_PRINTER_ADD("TONER-LOW", PRINTER_STATUS_TONER_LOW);
|
|
99
|
+
STATUS_PRINTER_ADD("USER-INTERVENTION", PRINTER_STATUS_USER_INTERVENTION);
|
|
100
|
+
STATUS_PRINTER_ADD("WAITING", PRINTER_STATUS_WAITING);
|
|
101
|
+
STATUS_PRINTER_ADD("WARMING-UP", PRINTER_STATUS_WARMING_UP);
|
|
102
|
+
#undef STATUS_PRINTER_ADD
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const StatusMapType& getJobStatusMap()
|
|
107
|
+
{
|
|
108
|
+
static StatusMapType result;
|
|
109
|
+
if(!result.empty())
|
|
110
|
+
{
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
// add only first time
|
|
114
|
+
#define STATUS_PRINTER_ADD(value, type) result.insert(std::make_pair(value, type))
|
|
115
|
+
// Common statuses
|
|
116
|
+
STATUS_PRINTER_ADD("PRINTING", JOB_STATUS_PRINTING);
|
|
117
|
+
STATUS_PRINTER_ADD("PRINTED", JOB_STATUS_PRINTED);
|
|
118
|
+
STATUS_PRINTER_ADD("PAUSED", JOB_STATUS_PAUSED);
|
|
119
|
+
|
|
120
|
+
// Specific statuses
|
|
121
|
+
STATUS_PRINTER_ADD("BLOCKED-DEVQ", JOB_STATUS_BLOCKED_DEVQ);
|
|
122
|
+
STATUS_PRINTER_ADD("DELETED", JOB_STATUS_DELETED);
|
|
123
|
+
STATUS_PRINTER_ADD("DELETING", JOB_STATUS_DELETING);
|
|
124
|
+
STATUS_PRINTER_ADD("ERROR", JOB_STATUS_ERROR);
|
|
125
|
+
STATUS_PRINTER_ADD("OFFLINE", JOB_STATUS_OFFLINE);
|
|
126
|
+
STATUS_PRINTER_ADD("PAPEROUT", JOB_STATUS_PAPEROUT);
|
|
127
|
+
STATUS_PRINTER_ADD("RESTART", JOB_STATUS_RESTART);
|
|
128
|
+
STATUS_PRINTER_ADD("SPOOLING", JOB_STATUS_SPOOLING);
|
|
129
|
+
STATUS_PRINTER_ADD("USER-INTERVENTION", JOB_STATUS_USER_INTERVENTION);
|
|
130
|
+
// XP and later
|
|
131
|
+
#ifdef JOB_STATUS_COMPLETE
|
|
132
|
+
STATUS_PRINTER_ADD("COMPLETE", JOB_STATUS_COMPLETE);
|
|
133
|
+
#endif
|
|
134
|
+
#ifdef JOB_STATUS_RETAINED
|
|
135
|
+
STATUS_PRINTER_ADD("RETAINED", JOB_STATUS_RETAINED);
|
|
136
|
+
#endif
|
|
137
|
+
|
|
138
|
+
#undef STATUS_PRINTER_ADD
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const StatusMapType& getAttributeMap()
|
|
143
|
+
{
|
|
144
|
+
static StatusMapType result;
|
|
145
|
+
if(!result.empty())
|
|
146
|
+
{
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
// add only first time
|
|
150
|
+
#define ATTRIBUTE_PRINTER_ADD(value, type) result.insert(std::make_pair(value, type))
|
|
151
|
+
ATTRIBUTE_PRINTER_ADD("DIRECT", PRINTER_ATTRIBUTE_DIRECT);
|
|
152
|
+
ATTRIBUTE_PRINTER_ADD("DO-COMPLETE-FIRST", PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST);
|
|
153
|
+
ATTRIBUTE_PRINTER_ADD("ENABLE-DEVQ", PRINTER_ATTRIBUTE_ENABLE_DEVQ);
|
|
154
|
+
ATTRIBUTE_PRINTER_ADD("HIDDEN", PRINTER_ATTRIBUTE_HIDDEN);
|
|
155
|
+
ATTRIBUTE_PRINTER_ADD("KEEPPRINTEDJOBS", PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS);
|
|
156
|
+
ATTRIBUTE_PRINTER_ADD("LOCAL", PRINTER_ATTRIBUTE_LOCAL);
|
|
157
|
+
ATTRIBUTE_PRINTER_ADD("NETWORK", PRINTER_ATTRIBUTE_NETWORK);
|
|
158
|
+
ATTRIBUTE_PRINTER_ADD("PUBLISHED", PRINTER_ATTRIBUTE_PUBLISHED);
|
|
159
|
+
ATTRIBUTE_PRINTER_ADD("QUEUED", PRINTER_ATTRIBUTE_QUEUED);
|
|
160
|
+
ATTRIBUTE_PRINTER_ADD("RAW-ONLY", PRINTER_ATTRIBUTE_RAW_ONLY);
|
|
161
|
+
ATTRIBUTE_PRINTER_ADD("SHARED", PRINTER_ATTRIBUTE_SHARED);
|
|
162
|
+
ATTRIBUTE_PRINTER_ADD("OFFLINE", PRINTER_ATTRIBUTE_WORK_OFFLINE);
|
|
163
|
+
// XP
|
|
164
|
+
#ifdef PRINTER_ATTRIBUTE_FAX
|
|
165
|
+
ATTRIBUTE_PRINTER_ADD("FAX", PRINTER_ATTRIBUTE_FAX);
|
|
166
|
+
#endif
|
|
167
|
+
// vista
|
|
168
|
+
#ifdef PRINTER_ATTRIBUTE_FRIENDLY_NAME
|
|
169
|
+
ATTRIBUTE_PRINTER_ADD("FRIENDLY-NAME", PRINTER_ATTRIBUTE_FRIENDLY_NAME);
|
|
170
|
+
ATTRIBUTE_PRINTER_ADD("MACHINE", PRINTER_ATTRIBUTE_MACHINE);
|
|
171
|
+
ATTRIBUTE_PRINTER_ADD("PUSHED-USER", PRINTER_ATTRIBUTE_PUSHED_USER);
|
|
172
|
+
ATTRIBUTE_PRINTER_ADD("PUSHED-MACHINE", PRINTER_ATTRIBUTE_PUSHED_MACHINE);
|
|
173
|
+
#endif
|
|
174
|
+
// server 2003
|
|
175
|
+
#ifdef PRINTER_ATTRIBUTE_TS
|
|
176
|
+
ATTRIBUTE_PRINTER_ADD("TS", PRINTER_ATTRIBUTE_TS);
|
|
177
|
+
#endif
|
|
178
|
+
#undef ATTRIBUTE_PRINTER_ADD
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const StatusMapType& getJobCommandMap()
|
|
183
|
+
{
|
|
184
|
+
static StatusMapType result;
|
|
185
|
+
if(!result.empty())
|
|
186
|
+
{
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
// add only first time
|
|
190
|
+
#define COMMAND_JOB_ADD(value, type) result.insert(std::make_pair(value, type))
|
|
191
|
+
COMMAND_JOB_ADD("CANCEL", JOB_CONTROL_CANCEL);
|
|
192
|
+
COMMAND_JOB_ADD("PAUSE", JOB_CONTROL_PAUSE);
|
|
193
|
+
COMMAND_JOB_ADD("RESTART", JOB_CONTROL_RESTART);
|
|
194
|
+
COMMAND_JOB_ADD("RESUME", JOB_CONTROL_RESUME);
|
|
195
|
+
COMMAND_JOB_ADD("DELETE", JOB_CONTROL_DELETE);
|
|
196
|
+
COMMAND_JOB_ADD("SENT-TO-PRINTER", JOB_CONTROL_SENT_TO_PRINTER);
|
|
197
|
+
COMMAND_JOB_ADD("LAST-PAGE-EJECTED", JOB_CONTROL_LAST_PAGE_EJECTED);
|
|
198
|
+
#ifdef JOB_CONTROL_RETAIN
|
|
199
|
+
COMMAND_JOB_ADD("RETAIN", JOB_CONTROL_RETAIN);
|
|
200
|
+
#endif
|
|
201
|
+
#ifdef JOB_CONTROL_RELEASE
|
|
202
|
+
COMMAND_JOB_ADD("RELEASE", JOB_CONTROL_RELEASE);
|
|
203
|
+
#endif
|
|
204
|
+
#undef COMMAND_JOB_ADD
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
void parseJobObject(JOB_INFO_2W *job, v8::Local<v8::Object> result_printer_job)
|
|
209
|
+
{
|
|
210
|
+
MY_NODE_MODULE_ISOLATE_DECL
|
|
211
|
+
//Common fields
|
|
212
|
+
//DWORD JobId;
|
|
213
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("id"), V8_VALUE_NEW(Number, job->JobId));
|
|
214
|
+
#define ADD_V8_STRING_PROPERTY(name, key) if((job->##key != NULL) && (*job->##key != L'\0')) \
|
|
215
|
+
{ \
|
|
216
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8(#name), V8_STRING_NEW_2BYTES((uint16_t*)job->##key)); \
|
|
217
|
+
}
|
|
218
|
+
//LPTSTR pPrinterName;
|
|
219
|
+
ADD_V8_STRING_PROPERTY(name, pPrinterName)
|
|
220
|
+
//LPTSTR pPrinterName;
|
|
221
|
+
ADD_V8_STRING_PROPERTY(printerName, pPrinterName);
|
|
222
|
+
//LPTSTR pUserName;
|
|
223
|
+
ADD_V8_STRING_PROPERTY(user, pUserName);
|
|
224
|
+
//LPTSTR pDatatype;
|
|
225
|
+
ADD_V8_STRING_PROPERTY(format, pDatatype);
|
|
226
|
+
//DWORD Priority;
|
|
227
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("priority"), V8_VALUE_NEW(Number, job->Priority));
|
|
228
|
+
//DWORD Size;
|
|
229
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("size"), V8_VALUE_NEW(Number, job->Size));
|
|
230
|
+
//DWORD Status;
|
|
231
|
+
v8::Local<v8::Array> result_printer_job_status = V8_VALUE_NEW_DEFAULT(Array);
|
|
232
|
+
int i_status = 0;
|
|
233
|
+
for(StatusMapType::const_iterator itStatus = getJobStatusMap().begin(); itStatus != getJobStatusMap().end(); ++itStatus)
|
|
234
|
+
{
|
|
235
|
+
if(job->Status & itStatus->second)
|
|
236
|
+
{
|
|
237
|
+
Nan::Set(result_printer_job_status, i_status++, V8_STRING_NEW_UTF8(itStatus->first.c_str()));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
//LPTSTR pStatus;
|
|
241
|
+
if((job->pStatus != NULL) && (*job->pStatus != L'\0'))
|
|
242
|
+
{
|
|
243
|
+
Nan::Set(result_printer_job_status, i_status++, V8_STRING_NEW_2BYTES((uint16_t*)job->pStatus));
|
|
244
|
+
}
|
|
245
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("status"), result_printer_job_status);
|
|
246
|
+
|
|
247
|
+
// Specific fields
|
|
248
|
+
//LPTSTR pMachineName;
|
|
249
|
+
ADD_V8_STRING_PROPERTY(machineName, pMachineName);
|
|
250
|
+
//LPTSTR pDocument;
|
|
251
|
+
ADD_V8_STRING_PROPERTY(document, pDocument);
|
|
252
|
+
//LPTSTR pNotifyName;
|
|
253
|
+
ADD_V8_STRING_PROPERTY(notifyName, pNotifyName);
|
|
254
|
+
//LPTSTR pPrintProcessor;
|
|
255
|
+
ADD_V8_STRING_PROPERTY(printProcessor, pPrintProcessor);
|
|
256
|
+
//LPTSTR pParameters;
|
|
257
|
+
ADD_V8_STRING_PROPERTY(parameters, pParameters);
|
|
258
|
+
//LPTSTR pDriverName;
|
|
259
|
+
ADD_V8_STRING_PROPERTY(driverName, pDriverName);
|
|
260
|
+
#undef ADD_V8_STRING_PROPERTY
|
|
261
|
+
//LPDEVMODE pDevMode;
|
|
262
|
+
//PSECURITY_DESCRIPTOR pSecurityDescriptor;
|
|
263
|
+
//DWORD Position;
|
|
264
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("position"), V8_VALUE_NEW(Number, job->Position));
|
|
265
|
+
//DWORD StartTime;
|
|
266
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("startTime"), V8_VALUE_NEW(Number, job->StartTime));
|
|
267
|
+
//DWORD UntilTime;
|
|
268
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("untilTime"), V8_VALUE_NEW(Number, job->UntilTime));
|
|
269
|
+
//DWORD TotalPages;
|
|
270
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("totalPages"), V8_VALUE_NEW(Number, job->TotalPages));
|
|
271
|
+
//SYSTEMTIME Submitted;
|
|
272
|
+
//DWORD Time;
|
|
273
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("time"), V8_VALUE_NEW(Number, job->Time));
|
|
274
|
+
//DWORD PagesPrinted;
|
|
275
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("pagesPrinted"), V8_VALUE_NEW(Number, job->PagesPrinted));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Returns last error code and message string
|
|
280
|
+
*/
|
|
281
|
+
std::string getLastErrorCodeAndMessage() {
|
|
282
|
+
std::ostringstream s;
|
|
283
|
+
DWORD erroCode = GetLastError();
|
|
284
|
+
s << "code: " << erroCode;
|
|
285
|
+
DWORD retSize;
|
|
286
|
+
LPTSTR pTemp = NULL;
|
|
287
|
+
retSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
|
|
288
|
+
FORMAT_MESSAGE_FROM_SYSTEM|
|
|
289
|
+
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
290
|
+
NULL,
|
|
291
|
+
erroCode,
|
|
292
|
+
LANG_NEUTRAL,
|
|
293
|
+
(LPTSTR)&pTemp,
|
|
294
|
+
0,
|
|
295
|
+
NULL );
|
|
296
|
+
if (retSize && pTemp != NULL) {
|
|
297
|
+
//pTemp[strlen(pTemp)-2]='\0'; //remove cr and newline character
|
|
298
|
+
//TODO: check if it is needed to convert c string to std::string
|
|
299
|
+
std::string stringMessage(pTemp);
|
|
300
|
+
s << ", message: " << stringMessage;
|
|
301
|
+
LocalFree((HLOCAL)pTemp);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return s.str();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
std::string retrieveAndParseJobs(const LPWSTR iPrinterName,
|
|
308
|
+
const DWORD& iTotalJobs,
|
|
309
|
+
v8::Local<v8::Object> result_printer_jobs,
|
|
310
|
+
PrinterHandle& iPrinterHandle)
|
|
311
|
+
{
|
|
312
|
+
MY_NODE_MODULE_ISOLATE_DECL
|
|
313
|
+
DWORD bytes_needed = 0, totalJobs = 0;
|
|
314
|
+
BOOL bError = EnumJobsW(*iPrinterHandle, 0, iTotalJobs, 2, NULL, bytes_needed, &bytes_needed, &totalJobs);
|
|
315
|
+
MemValue<JOB_INFO_2W> jobs(bytes_needed);
|
|
316
|
+
if(!jobs)
|
|
317
|
+
{
|
|
318
|
+
std::string error_str("Error on allocating memory for jobs: ");
|
|
319
|
+
error_str += getLastErrorCodeAndMessage();
|
|
320
|
+
v8::Local<v8::Object> result_printer_job = V8_VALUE_NEW_DEFAULT(Object);
|
|
321
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("error"), V8_STRING_NEW_UTF8(error_str.c_str()));
|
|
322
|
+
Nan::Set(result_printer_jobs, 0, result_printer_job);
|
|
323
|
+
return std::string("");
|
|
324
|
+
}
|
|
325
|
+
DWORD dummy_bytes = 0;
|
|
326
|
+
bError = EnumJobsW(*iPrinterHandle, 0, iTotalJobs, 2, (LPBYTE)jobs.get(), bytes_needed, &dummy_bytes, &totalJobs);
|
|
327
|
+
if(!bError)
|
|
328
|
+
{
|
|
329
|
+
std::string error_str("Error on EnumJobsW: ");
|
|
330
|
+
error_str += getLastErrorCodeAndMessage();
|
|
331
|
+
v8::Local<v8::Object> result_printer_job = V8_VALUE_NEW_DEFAULT(Object);
|
|
332
|
+
Nan::Set(result_printer_job, V8_STRING_NEW_UTF8("error"), V8_STRING_NEW_UTF8(error_str.c_str()));
|
|
333
|
+
Nan::Set(result_printer_jobs, 0, result_printer_job);
|
|
334
|
+
return std::string("");
|
|
335
|
+
}
|
|
336
|
+
JOB_INFO_2W *job = jobs.get();
|
|
337
|
+
for(DWORD i = 0; i < totalJobs; ++i, ++job)
|
|
338
|
+
{
|
|
339
|
+
v8::Local<v8::Object> result_printer_job = V8_VALUE_NEW_DEFAULT(Object);
|
|
340
|
+
parseJobObject(job, result_printer_job);
|
|
341
|
+
Nan::Set(result_printer_jobs, i, result_printer_job);
|
|
342
|
+
}
|
|
343
|
+
return std::string("");
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
std::string parsePrinterInfo(const PRINTER_INFO_2W *printer, v8::Local<v8::Object> result_printer, PrinterHandle& iPrinterHandle)
|
|
347
|
+
{
|
|
348
|
+
MY_NODE_MODULE_ISOLATE_DECL
|
|
349
|
+
#define ADD_V8_STRING_PROPERTY(name, key) if((printer->##key != NULL) && (*printer->##key != L'\0')) \
|
|
350
|
+
{ \
|
|
351
|
+
Nan::Set(result_printer, V8_STRING_NEW_UTF8(#name), V8_STRING_NEW_2BYTES((uint16_t*)printer->##key)); \
|
|
352
|
+
}
|
|
353
|
+
//LPTSTR pPrinterName;
|
|
354
|
+
ADD_V8_STRING_PROPERTY(name, pPrinterName)
|
|
355
|
+
//LPTSTR pServerName;
|
|
356
|
+
ADD_V8_STRING_PROPERTY(serverName, pServerName)
|
|
357
|
+
//LPTSTR pShareName;
|
|
358
|
+
ADD_V8_STRING_PROPERTY(shareName, pShareName)
|
|
359
|
+
//LPTSTR pPortName;
|
|
360
|
+
ADD_V8_STRING_PROPERTY(portName, pPortName)
|
|
361
|
+
//LPTSTR pDriverName;
|
|
362
|
+
ADD_V8_STRING_PROPERTY(driverName, pDriverName)
|
|
363
|
+
//LPTSTR pComment;
|
|
364
|
+
ADD_V8_STRING_PROPERTY(comment, pComment)
|
|
365
|
+
//LPTSTR pLocation;
|
|
366
|
+
ADD_V8_STRING_PROPERTY(location, pLocation)
|
|
367
|
+
//LPTSTR pSepFile;
|
|
368
|
+
ADD_V8_STRING_PROPERTY(sepFile, pSepFile)
|
|
369
|
+
//LPTSTR pPrintProcessor;
|
|
370
|
+
ADD_V8_STRING_PROPERTY(printProcessor, pPrintProcessor)
|
|
371
|
+
//LPTSTR pDatatype;
|
|
372
|
+
ADD_V8_STRING_PROPERTY(datatype, pDatatype)
|
|
373
|
+
//LPTSTR pParameters;
|
|
374
|
+
ADD_V8_STRING_PROPERTY(parameters, pParameters)
|
|
375
|
+
#undef ADD_V8_STRING_PROPERTY
|
|
376
|
+
//DWORD Status;
|
|
377
|
+
// statuses from:
|
|
378
|
+
// http://msdn.microsoft.com/en-gb/library/windows/desktop/dd162845(v=vs.85).aspx
|
|
379
|
+
v8::Local<v8::Array> result_printer_status = V8_VALUE_NEW_DEFAULT(Array);
|
|
380
|
+
int i_status = 0;
|
|
381
|
+
for(StatusMapType::const_iterator itStatus = getStatusMap().begin(); itStatus != getStatusMap().end(); ++itStatus)
|
|
382
|
+
{
|
|
383
|
+
if(printer->Status & itStatus->second)
|
|
384
|
+
{
|
|
385
|
+
Nan::Set(result_printer_status, i_status, V8_STRING_NEW_UTF8(itStatus->first.c_str()));
|
|
386
|
+
++i_status;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
Nan::Set(result_printer, V8_STRING_NEW_UTF8("status"), result_printer_status);
|
|
390
|
+
Nan::Set(result_printer, V8_STRING_NEW_UTF8("statusNumber"), V8_VALUE_NEW(Number, printer->Status));
|
|
391
|
+
//DWORD Attributes;
|
|
392
|
+
v8::Local<v8::Array> result_printer_attributes = V8_VALUE_NEW_DEFAULT(Array);
|
|
393
|
+
int i_attribute = 0;
|
|
394
|
+
for(StatusMapType::const_iterator itAttribute = getAttributeMap().begin(); itAttribute != getAttributeMap().end(); ++itAttribute)
|
|
395
|
+
{
|
|
396
|
+
if(printer->Attributes & itAttribute->second)
|
|
397
|
+
{
|
|
398
|
+
Nan::Set(result_printer_attributes, i_attribute, V8_STRING_NEW_UTF8(itAttribute->first.c_str()));
|
|
399
|
+
++i_attribute;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
Nan::Set(result_printer, V8_STRING_NEW_UTF8("attributes"), result_printer_attributes);
|
|
403
|
+
//DWORD Priority;
|
|
404
|
+
Nan::Set(result_printer, V8_STRING_NEW_UTF8("priority"), V8_VALUE_NEW(Number, printer->Priority));
|
|
405
|
+
//DWORD DefaultPriority;
|
|
406
|
+
Nan::Set(result_printer, V8_STRING_NEW_UTF8("defaultPriority"), V8_VALUE_NEW(Number, printer->DefaultPriority));
|
|
407
|
+
//DWORD cJobs;
|
|
408
|
+
//Nan::Set(result_printer, V8_STRING_NEW_UTF8("jobs"), V8_VALUE_NEW(Number, printer->cJobs));
|
|
409
|
+
//DWORD AveragePPM;
|
|
410
|
+
Nan::Set(result_printer, V8_STRING_NEW_UTF8("averagePPM"), V8_VALUE_NEW(Number, printer->AveragePPM));
|
|
411
|
+
|
|
412
|
+
//DWORD StartTime;
|
|
413
|
+
if(printer->StartTime > 0)
|
|
414
|
+
{
|
|
415
|
+
Nan::Set(result_printer, V8_STRING_NEW_UTF8("startTime"), V8_VALUE_NEW(Number, printer->StartTime));
|
|
416
|
+
}
|
|
417
|
+
//DWORD UntilTime;
|
|
418
|
+
if(printer->UntilTime > 0)
|
|
419
|
+
{
|
|
420
|
+
Nan::Set(result_printer, V8_STRING_NEW_UTF8("untilTime"), V8_VALUE_NEW(Number, printer->UntilTime));
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
//TODO: to finish to extract all data
|
|
424
|
+
//LPDEVMODE pDevMode;
|
|
425
|
+
//PSECURITY_DESCRIPTOR pSecurityDescriptor;
|
|
426
|
+
|
|
427
|
+
if(printer->cJobs > 0)
|
|
428
|
+
{
|
|
429
|
+
v8::Local<v8::Array> result_printer_jobs = V8_VALUE_NEW(Array, printer->cJobs);
|
|
430
|
+
// get jobs
|
|
431
|
+
std::string error_str = retrieveAndParseJobs(printer->pPrinterName, printer->cJobs, result_printer_jobs, iPrinterHandle);
|
|
432
|
+
if(!error_str.empty())
|
|
433
|
+
{
|
|
434
|
+
return error_str;
|
|
435
|
+
}
|
|
436
|
+
Nan::Set(result_printer, V8_STRING_NEW_UTF8("jobs"), result_printer_jobs);
|
|
437
|
+
}
|
|
438
|
+
return "";
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
MY_NODE_MODULE_CALLBACK(getPrinters)
|
|
443
|
+
{
|
|
444
|
+
MY_NODE_MODULE_HANDLESCOPE;
|
|
445
|
+
DWORD printers_size = 0;
|
|
446
|
+
DWORD printers_size_bytes = 0, dummyBytes = 0;
|
|
447
|
+
DWORD Level = 2;
|
|
448
|
+
DWORD flags = PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS;// https://msdn.microsoft.com/en-us/library/cc244669.aspx
|
|
449
|
+
// First try to retrieve the number of printers
|
|
450
|
+
BOOL bError = EnumPrintersW(flags, NULL, 2, NULL, 0, &printers_size_bytes, &printers_size);
|
|
451
|
+
// allocate the required memmory
|
|
452
|
+
MemValue<PRINTER_INFO_2W> printers(printers_size_bytes);
|
|
453
|
+
if(!printers)
|
|
454
|
+
{
|
|
455
|
+
RETURN_EXCEPTION_STR("Error on allocating memory for printers");
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
bError = EnumPrintersW(flags, NULL, 2, (LPBYTE)(printers.get()), printers_size_bytes, &dummyBytes, &printers_size);
|
|
459
|
+
if(!bError)
|
|
460
|
+
{
|
|
461
|
+
std::string error_str("Error on EnumPrinters: ");
|
|
462
|
+
error_str += getLastErrorCodeAndMessage();
|
|
463
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
464
|
+
}
|
|
465
|
+
v8::Local<v8::Array> result = V8_VALUE_NEW(Array, printers_size);
|
|
466
|
+
// http://msdn.microsoft.com/en-gb/library/windows/desktop/dd162845(v=vs.85).aspx
|
|
467
|
+
PRINTER_INFO_2W *printer = printers.get();
|
|
468
|
+
DWORD i = 0;
|
|
469
|
+
for(; i < printers_size; ++i, ++printer)
|
|
470
|
+
{
|
|
471
|
+
v8::Local<v8::Object> result_printer = V8_VALUE_NEW_DEFAULT(Object);
|
|
472
|
+
PrinterHandle printerHandle((LPWSTR)(printer->pPrinterName));
|
|
473
|
+
std::string error_str = parsePrinterInfo(printer, result_printer, printerHandle);
|
|
474
|
+
if(!error_str.empty())
|
|
475
|
+
{
|
|
476
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
477
|
+
}
|
|
478
|
+
Nan::Set(result, i, result_printer);
|
|
479
|
+
}
|
|
480
|
+
MY_NODE_MODULE_RETURN_VALUE(result);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
MY_NODE_MODULE_CALLBACK(getDefaultPrinterName)
|
|
484
|
+
{
|
|
485
|
+
MY_NODE_MODULE_HANDLESCOPE;
|
|
486
|
+
// size in chars of the printer name: https://msdn.microsoft.com/en-us/library/windows/desktop/dd144876(v=vs.85).aspx
|
|
487
|
+
DWORD cSize = 0;
|
|
488
|
+
GetDefaultPrinterW(NULL, &cSize);
|
|
489
|
+
|
|
490
|
+
if(cSize == 0) {
|
|
491
|
+
MY_NODE_MODULE_RETURN_VALUE(V8_STRING_NEW_UTF8(""));
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
MemValue<uint16_t> bPrinterName(cSize*sizeof(uint16_t));
|
|
495
|
+
BOOL res = GetDefaultPrinterW((LPWSTR)(bPrinterName.get()), &cSize);
|
|
496
|
+
|
|
497
|
+
if(!res) {
|
|
498
|
+
MY_NODE_MODULE_RETURN_VALUE(V8_STRING_NEW_UTF8(""));
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
MY_NODE_MODULE_RETURN_VALUE(V8_STRING_NEW_2BYTES((uint16_t*)bPrinterName.get()));
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
MY_NODE_MODULE_CALLBACK(getPrinter)
|
|
505
|
+
{
|
|
506
|
+
MY_NODE_MODULE_HANDLESCOPE;
|
|
507
|
+
REQUIRE_ARGUMENTS(iArgs, 1);
|
|
508
|
+
REQUIRE_ARGUMENT_STRINGW(iArgs, 0, printername);
|
|
509
|
+
|
|
510
|
+
// Open a handle to the printer.
|
|
511
|
+
PrinterHandle printerHandle((LPWSTR)(*printername));
|
|
512
|
+
if(!printerHandle)
|
|
513
|
+
{
|
|
514
|
+
std::string error_str("error on PrinterHandle: ");
|
|
515
|
+
error_str += getLastErrorCodeAndMessage();
|
|
516
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
517
|
+
}
|
|
518
|
+
DWORD printers_size_bytes = 0, dummyBytes = 0;
|
|
519
|
+
GetPrinterW(*printerHandle, 2, NULL, printers_size_bytes, &printers_size_bytes);
|
|
520
|
+
MemValue<PRINTER_INFO_2W> printer(printers_size_bytes);
|
|
521
|
+
if(!printer)
|
|
522
|
+
{
|
|
523
|
+
RETURN_EXCEPTION_STR("Error on allocating memory for printers");
|
|
524
|
+
}
|
|
525
|
+
BOOL bOK = GetPrinterW(*printerHandle, 2, (LPBYTE)(printer.get()), printers_size_bytes, &printers_size_bytes);
|
|
526
|
+
if(!bOK)
|
|
527
|
+
{
|
|
528
|
+
std::string error_str("Error on GetPrinter: ");
|
|
529
|
+
error_str += getLastErrorCodeAndMessage();
|
|
530
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
531
|
+
}
|
|
532
|
+
v8::Local<v8::Object> result_printer = V8_VALUE_NEW_DEFAULT(Object);
|
|
533
|
+
std::string error_str = parsePrinterInfo(printer.get(), result_printer, printerHandle);
|
|
534
|
+
if(!error_str.empty())
|
|
535
|
+
{
|
|
536
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
MY_NODE_MODULE_RETURN_VALUE(result_printer);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
MY_NODE_MODULE_CALLBACK(getPrinterDriverOptions)
|
|
543
|
+
{
|
|
544
|
+
MY_NODE_MODULE_HANDLESCOPE;
|
|
545
|
+
RETURN_EXCEPTION_STR("not supported on windows");
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
MY_NODE_MODULE_CALLBACK(getJob)
|
|
549
|
+
{
|
|
550
|
+
MY_NODE_MODULE_HANDLESCOPE;
|
|
551
|
+
REQUIRE_ARGUMENTS(iArgs, 2);
|
|
552
|
+
REQUIRE_ARGUMENT_STRINGW(iArgs, 0, printername);
|
|
553
|
+
REQUIRE_ARGUMENT_INTEGER(iArgs, 1, jobId);
|
|
554
|
+
if(jobId < 0)
|
|
555
|
+
{
|
|
556
|
+
RETURN_EXCEPTION_STR("Wrong job number");
|
|
557
|
+
}
|
|
558
|
+
// Open a handle to the printer.
|
|
559
|
+
PrinterHandle printerHandle((LPWSTR)(*printername));
|
|
560
|
+
if(!printerHandle)
|
|
561
|
+
{
|
|
562
|
+
std::string error_str("error on PrinterHandle: ");
|
|
563
|
+
error_str += getLastErrorCodeAndMessage();
|
|
564
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
565
|
+
}
|
|
566
|
+
DWORD size_bytes = 0, dummyBytes = 0;
|
|
567
|
+
GetJobW(*printerHandle, static_cast<DWORD>(jobId), 2, NULL, size_bytes, &size_bytes);
|
|
568
|
+
MemValue<JOB_INFO_2W> job(size_bytes);
|
|
569
|
+
if(!job)
|
|
570
|
+
{
|
|
571
|
+
RETURN_EXCEPTION_STR("Error on allocating memory for printers");
|
|
572
|
+
}
|
|
573
|
+
BOOL bOK = GetJobW(*printerHandle, static_cast<DWORD>(jobId), 2, (LPBYTE)job.get(), size_bytes, &dummyBytes);
|
|
574
|
+
if(!bOK)
|
|
575
|
+
{
|
|
576
|
+
std::string error_str("Error on GetJob. Wrong job id or it was deleted: ");
|
|
577
|
+
error_str += getLastErrorCodeAndMessage();
|
|
578
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
579
|
+
}
|
|
580
|
+
v8::Local<v8::Object> result_printer_job = V8_VALUE_NEW_DEFAULT(Object);
|
|
581
|
+
parseJobObject(job.get(), result_printer_job);
|
|
582
|
+
MY_NODE_MODULE_RETURN_VALUE(result_printer_job);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
MY_NODE_MODULE_CALLBACK(setJob)
|
|
586
|
+
{
|
|
587
|
+
MY_NODE_MODULE_HANDLESCOPE;
|
|
588
|
+
REQUIRE_ARGUMENTS(iArgs, 3);
|
|
589
|
+
REQUIRE_ARGUMENT_STRINGW(iArgs, 0, printername);
|
|
590
|
+
REQUIRE_ARGUMENT_INTEGER(iArgs, 1, jobId);
|
|
591
|
+
REQUIRE_ARGUMENT_STRING(iArgs, 2, jobCommandV8);
|
|
592
|
+
if(jobId < 0)
|
|
593
|
+
{
|
|
594
|
+
RETURN_EXCEPTION_STR("Wrong job number");
|
|
595
|
+
}
|
|
596
|
+
std::string jobCommandStr(*jobCommandV8);
|
|
597
|
+
StatusMapType::const_iterator itJobCommand = getJobCommandMap().find(jobCommandStr);
|
|
598
|
+
if(itJobCommand == getJobCommandMap().end())
|
|
599
|
+
{
|
|
600
|
+
RETURN_EXCEPTION_STR("wrong job command. use getSupportedJobCommands to see the possible commands");
|
|
601
|
+
}
|
|
602
|
+
DWORD jobCommand = itJobCommand->second;
|
|
603
|
+
// Open a handle to the printer.
|
|
604
|
+
PrinterHandle printerHandle((LPWSTR)(*printername));
|
|
605
|
+
if(!printerHandle)
|
|
606
|
+
{
|
|
607
|
+
std::string error_str("error on PrinterHandle: ");
|
|
608
|
+
error_str += getLastErrorCodeAndMessage();
|
|
609
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
610
|
+
}
|
|
611
|
+
// TODO: add the possibility to set job properties
|
|
612
|
+
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162978(v=vs.85).aspx
|
|
613
|
+
BOOL ok = SetJobW(*printerHandle, (DWORD)jobId, 0, NULL, jobCommand);
|
|
614
|
+
MY_NODE_MODULE_RETURN_VALUE(V8_VALUE_NEW(Boolean, ok == TRUE));
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
MY_NODE_MODULE_CALLBACK(getSupportedJobCommands)
|
|
618
|
+
{
|
|
619
|
+
MY_NODE_MODULE_HANDLESCOPE;
|
|
620
|
+
v8::Local<v8::Array> result = V8_VALUE_NEW_DEFAULT(Array);
|
|
621
|
+
int i = 0;
|
|
622
|
+
for(StatusMapType::const_iterator itJob = getJobCommandMap().begin(); itJob != getJobCommandMap().end(); ++itJob)
|
|
623
|
+
{
|
|
624
|
+
Nan::Set(result, i++, V8_STRING_NEW_UTF8(itJob->first.c_str()));
|
|
625
|
+
}
|
|
626
|
+
MY_NODE_MODULE_RETURN_VALUE(result);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
MY_NODE_MODULE_CALLBACK(getSupportedPrintFormats)
|
|
630
|
+
{
|
|
631
|
+
MY_NODE_MODULE_HANDLESCOPE;
|
|
632
|
+
v8::Local<v8::Array> result = V8_VALUE_NEW_DEFAULT(Array);
|
|
633
|
+
int format_i = 0;
|
|
634
|
+
|
|
635
|
+
LPTSTR name = NULL;
|
|
636
|
+
DWORD numBytes = 0, processorsNum = 0;
|
|
637
|
+
|
|
638
|
+
// Check the amount of bytes required
|
|
639
|
+
LPWSTR nullVal = NULL;
|
|
640
|
+
EnumPrintProcessorsW(nullVal, nullVal, 1, (LPBYTE)(NULL), numBytes, &numBytes, &processorsNum);
|
|
641
|
+
MemValue<_PRINTPROCESSOR_INFO_1W> processors(numBytes);
|
|
642
|
+
// Retrieve processors
|
|
643
|
+
BOOL isOK = EnumPrintProcessorsW(nullVal, nullVal, 1, (LPBYTE)(processors.get()), numBytes, &numBytes, &processorsNum);
|
|
644
|
+
|
|
645
|
+
if(!isOK) {
|
|
646
|
+
std::string error_str("error on EnumPrintProcessorsW: ");
|
|
647
|
+
error_str += getLastErrorCodeAndMessage();
|
|
648
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
_PRINTPROCESSOR_INFO_1W *pProcessor = processors.get();
|
|
652
|
+
|
|
653
|
+
for(DWORD processor_i = 0; processor_i < processorsNum; ++processor_i, ++pProcessor) {
|
|
654
|
+
numBytes = 0;
|
|
655
|
+
DWORD dataTypesNum = 0;
|
|
656
|
+
EnumPrintProcessorDatatypesW(nullVal, pProcessor->pName, 1, (LPBYTE)(NULL), numBytes, &numBytes, &dataTypesNum);
|
|
657
|
+
MemValue<_DATATYPES_INFO_1W> dataTypes(numBytes);
|
|
658
|
+
isOK = EnumPrintProcessorDatatypesW(nullVal, pProcessor->pName, 1, (LPBYTE)(dataTypes.get()), numBytes, &numBytes, &dataTypesNum);
|
|
659
|
+
|
|
660
|
+
if(!isOK) {
|
|
661
|
+
std::string error_str("error on EnumPrintProcessorDatatypesW: ");
|
|
662
|
+
error_str += getLastErrorCodeAndMessage();
|
|
663
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
_DATATYPES_INFO_1W *pDataType = dataTypes.get();
|
|
667
|
+
for(DWORD j = 0; j < dataTypesNum; ++j, ++pDataType) {
|
|
668
|
+
Nan::Set(result, format_i++, V8_STRING_NEW_2BYTES((uint16_t*)(pDataType->pName)));
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
MY_NODE_MODULE_RETURN_VALUE(result);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
MY_NODE_MODULE_CALLBACK(PrintDirect)
|
|
676
|
+
{
|
|
677
|
+
MY_NODE_MODULE_HANDLESCOPE;
|
|
678
|
+
//TODO: to move in an unique place win and posix input parameters processing
|
|
679
|
+
REQUIRE_ARGUMENTS(iArgs, 5);
|
|
680
|
+
|
|
681
|
+
// can be string or buffer
|
|
682
|
+
if(iArgs.Length()<=0)
|
|
683
|
+
{
|
|
684
|
+
RETURN_EXCEPTION_STR("Argument 0 missing");
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
std::string data;
|
|
688
|
+
v8::Local<v8::Value> arg0(iArgs[0]);
|
|
689
|
+
if (!getStringOrBufferFromV8Value(arg0, data))
|
|
690
|
+
{
|
|
691
|
+
RETURN_EXCEPTION_STR("Argument 0 must be a string or Buffer");
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
REQUIRE_ARGUMENT_STRINGW(iArgs, 1, printername);
|
|
695
|
+
REQUIRE_ARGUMENT_STRINGW(iArgs, 2, docname);
|
|
696
|
+
REQUIRE_ARGUMENT_STRINGW(iArgs, 3, type);
|
|
697
|
+
|
|
698
|
+
BOOL bStatus = true;
|
|
699
|
+
// Open a handle to the printer.
|
|
700
|
+
PrinterHandle printerHandle((LPWSTR)(*printername));
|
|
701
|
+
DOC_INFO_1W DocInfo;
|
|
702
|
+
DWORD dwJob = 0L;
|
|
703
|
+
DWORD dwBytesWritten = 0L;
|
|
704
|
+
|
|
705
|
+
if (!printerHandle)
|
|
706
|
+
{
|
|
707
|
+
std::string error_str("error on PrinterHandle: ");
|
|
708
|
+
error_str += getLastErrorCodeAndMessage();
|
|
709
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// Fill in the structure with info about this "document."
|
|
713
|
+
DocInfo.pDocName = (LPWSTR)(*docname);
|
|
714
|
+
DocInfo.pOutputFile = NULL;
|
|
715
|
+
DocInfo.pDatatype = (LPWSTR)(*type);
|
|
716
|
+
|
|
717
|
+
// Inform the spooler the document is beginning.
|
|
718
|
+
dwJob = StartDocPrinterW(*printerHandle, 1, (LPBYTE)&DocInfo );
|
|
719
|
+
if (dwJob > 0) {
|
|
720
|
+
// Start a page.
|
|
721
|
+
bStatus = StartPagePrinter(*printerHandle);
|
|
722
|
+
if (bStatus) {
|
|
723
|
+
// Send the data to the printer.
|
|
724
|
+
//TODO: check with sizeof(LPTSTR) is the same as sizeof(char)
|
|
725
|
+
bStatus = WritePrinter( *printerHandle, (LPVOID)(data.c_str()), (DWORD)data.size(), &dwBytesWritten);
|
|
726
|
+
EndPagePrinter(*printerHandle);
|
|
727
|
+
}else{
|
|
728
|
+
std::string error_str("StartPagePrinter error: ");
|
|
729
|
+
error_str += getLastErrorCodeAndMessage();
|
|
730
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
731
|
+
}
|
|
732
|
+
// Inform the spooler that the document is ending.
|
|
733
|
+
EndDocPrinter(*printerHandle);
|
|
734
|
+
}else{
|
|
735
|
+
std::string error_str("StartDocPrinterW error: ");
|
|
736
|
+
error_str += getLastErrorCodeAndMessage();
|
|
737
|
+
RETURN_EXCEPTION_STR(error_str.c_str());
|
|
738
|
+
}
|
|
739
|
+
// Check to see if correct number of bytes were written.
|
|
740
|
+
if (dwBytesWritten != data.size()) {
|
|
741
|
+
RETURN_EXCEPTION_STR("not sent all bytes");
|
|
742
|
+
}
|
|
743
|
+
MY_NODE_MODULE_RETURN_VALUE(V8_VALUE_NEW(Number, dwJob));
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
MY_NODE_MODULE_CALLBACK(PrintFile)
|
|
747
|
+
{
|
|
748
|
+
MY_NODE_MODULE_HANDLESCOPE;
|
|
749
|
+
RETURN_EXCEPTION_STR("Not yet implemented on Windows");
|
|
750
|
+
}
|