1#define PRINTDRIVER
2
3#include "stdafx.h"
4
5#include "beCompat.h"
6#include "betalk.h"
7#include "authentication.h"
8#include "printing.h"
9
10#include "string.h"
11#include "winspool.h"
12#include "stdio.h"
13
14
15extern void btMakePath(char *path, char *dir, char *file);
16extern bt_printer *btFindPrinter(char *printerName);
17
18DWORD WINAPI printerThread(LPVOID data);
19void CheckPrintJobStatus(bt_printer *printer, char *printJob);
20bool PrintFile(bt_printer *printer, char *jobName, char *filename);
21
22
23// printerThread()
24//
25DWORD WINAPI printerThread(LPVOID data)
26{
27	bt_printer *printer = (bt_printer *) data;
28	struct _finddata_t fileInfo;
29	char search[B_PATH_NAME_LENGTH], path[B_PATH_NAME_LENGTH];
30	long int result, finder;
31
32	if (!data)
33		return 0;
34
35	// Create the search path for all .job files in the spool folder.
36	btMakePath(search, printer->spoolDir, "*.job");
37
38	while (!printer->killed)
39	{
40		// Find the first print job.
41		finder = result = _findfirst(search, &fileInfo);
42		while (result != -1)
43		{
44			// Create the fully-qualified path to this print job file, then check
45			// its status.
46			btMakePath(path, printer->spoolDir, fileInfo.name);
47			CheckPrintJobStatus(printer, path);
48
49			// Get the next print job.
50			result = _findnext(finder, &fileInfo);
51		}
52
53		// Close our job search and wait awhile.
54		_findclose(finder);
55		Sleep(2000);
56	}
57
58	return 0;
59}
60
61// CheckPrintJobStatus()
62//
63void CheckPrintJobStatus(bt_printer *printer, char *printJob)
64{
65	char dataPath[B_PATH_NAME_LENGTH], dataFile[B_FILE_NAME_LENGTH];
66	char jobName[B_FILE_NAME_LENGTH], status[50];
67
68	GetPrivateProfileString("PrintJob", "Status", "", status, sizeof(status), printJob);
69
70	if (stricmp(status, "Scheduling...") == 0)
71	{
72		// Move status from scheduling to printing.
73		WritePrivateProfileString("PrintJob", "Status", "Printing...", printJob);
74
75		// Get the name of the spooled file and print it.
76		GetPrivateProfileString("PrintJob", "JobName", "", jobName, sizeof(jobName), printJob);
77		GetPrivateProfileString("PrintJob", "DataFile", "", dataFile, sizeof(dataFile), printJob);
78		btMakePath(dataPath, printer->spoolDir, dataFile);
79		PrintFile(printer, jobName, dataPath);
80
81		// Remove the job and data files.
82		remove(dataPath);
83		remove(printJob);
84	}
85}
86
87// PrintFile()
88//
89bool PrintFile(bt_printer *printer, char *jobName, char *fileName)
90{
91	HANDLE hPrinter;
92	DOC_INFO_1 docInfo;
93	DWORD dwJob, bytesSent;
94	size_t bytes;
95
96	// Allocate a buffer for print data.
97	char *buffer = (char *) malloc(BT_MAX_IO_BUFFER + 1);
98	if (!buffer)
99		return false;
100
101	// Open the file for reading
102	FILE *fp = fopen(fileName, "rb");
103	if (!fp)
104	{
105		free(buffer);
106		return false;
107	}
108
109	// Need a handle to the printer.
110	if (OpenPrinter(printer->deviceName, &hPrinter, NULL))
111	{
112		// Fill in the structure with info about this "document."
113		docInfo.pDocName = jobName;
114		docInfo.pOutputFile = NULL;
115		docInfo.pDatatype = "RAW";
116
117		// Inform the spooler the document is beginning.
118		if ((dwJob = StartDocPrinter(hPrinter, 1, (unsigned char *) &docInfo)) != 0)
119		{
120			// Start a page.
121			if (StartPagePrinter(hPrinter))
122			{
123				// Send the data to the printer.
124				// Print the file 8K at a time, until we are finished or shut down.
125				while (!printer->killed)
126				{
127					bytes = fread(buffer, 1, BT_MAX_IO_BUFFER, fp);
128					if (bytes <= 0)
129						break;
130
131					if (!WritePrinter(hPrinter, buffer, bytes, &bytesSent))
132						break;
133				}
134
135				EndPagePrinter(hPrinter);
136			}
137
138			EndDocPrinter(hPrinter);
139		}
140
141		ClosePrinter(hPrinter);
142	}
143
144	if (ferror(fp))
145		clearerr(fp);
146
147	fclose(fp);
148	free(buffer);
149	return true;
150}
151
152// btPrintJobNew()
153//
154int btPrintJobNew(char *printerName, char *user, char *password, int client_s_addr, char *jobName, char *jobId)
155{
156	char printJob[B_PATH_NAME_LENGTH], dataFile[B_PATH_NAME_LENGTH], addr[40];
157	bt_printer *printer = btFindPrinter(printerName);
158	bt_user_rights *ur;
159	char *groups[MAX_GROUPS_PER_USER];
160	int i, rights;
161	bool authenticated = false;
162
163	// Create a new print job by writing the <jobId>.job file and by
164	// creating the <jobId>.prn file.
165	if (printer)
166	{
167		SYSTEMTIME st;
168		int docId = 0;
169
170		// Verify the user has permission to print.
171		if (printer->security != BT_AUTH_NONE)
172		{
173			// Authenticate the user with name/password.
174			authenticated = authenticateUser(user, password);
175			if (!authenticated)
176				return BEOS_EACCES;
177
178			// Does the authenticated user have any rights on this file share?
179			rights = 0;
180			for (ur = printer->rights; ur; ur = ur->next)
181				if (!ur->isGroup && stricmp(ur->user, user) == 0)
182					rights |= ur->rights;
183
184			// Does the authenticated user belong to any groups that have any rights on this
185			// file share?
186			for (i = 0; i < MAX_GROUPS_PER_USER; i++)
187				groups[i] = NULL;
188
189			getUserGroups(user, groups);
190			for (ur = printer->rights; ur; ur = ur->next)
191				if (ur->isGroup)
192					for (i = 0; i < MAX_GROUPS_PER_USER; i++)
193						if (groups[i] && stricmp(ur->user, groups[i]) == 0)
194						{
195							rights |= ur->rights;
196							break;
197						}
198
199			// Free the memory occupied by the group list.
200			for (i = 0; i < MAX_GROUPS_PER_USER; i++)
201				if (groups[i])
202					free(groups[i]);
203
204			// If no rights have been granted, deny access.
205			if (!(rights & BT_RIGHTS_PRINT))
206				return BEOS_EACCES;
207		}
208
209		// Create a new job ID.
210		do
211		{
212			GetSystemTime(&st);
213			sprintf(jobId, "%x-%03d-%d", time(NULL), st.wMilliseconds, docId++);
214			sprintf(printJob, "%s\\%s.job", printer->spoolDir, jobId);
215		} while (access(printJob, 0) == 0);
216
217		// Write the job information file.
218		sprintf(dataFile, "%s.prn", jobId);
219		WritePrivateProfileString("PrintJob", "JobName", jobName, printJob);
220		WritePrivateProfileString("PrintJob", "Status", "Queueing...", printJob);
221		WritePrivateProfileString("PrintJob", "DataFile", dataFile, printJob);
222		WritePrivateProfileString("PrintJob", "User", user, printJob);
223
224		uint8 *_s_addr = (uint8 *) &client_s_addr;
225		sprintf(addr, "%d.%d.%d.%d", _s_addr[0], _s_addr[1], _s_addr[2], _s_addr[3]);
226		WritePrivateProfileString("PrintJob", "Source", addr, printJob);
227
228		// Now create the empty data file.
229		sprintf(dataFile, "%s\\%s.prn", printer->spoolDir, jobId);
230//		_creat(dataFile, _S_IWRITE);
231		HANDLE hFile = CreateFile(dataFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
232		CloseHandle(hFile);
233
234		return B_OK;
235	}
236
237	return BEOS_ENOENT;
238}
239
240// btPrintJobData()
241//
242int btPrintJobData(char *printerName, char *jobId, char *jobData, int dataLen)
243{
244	char printJob[B_PATH_NAME_LENGTH];
245	bt_printer *printer = btFindPrinter(printerName);
246	FILE *fp;
247
248	if (printer)
249	{
250		sprintf(printJob, "%s\\%s.job", printer->spoolDir, jobId);
251		if (access(printJob, 0) == 0)
252		{
253			sprintf(printJob, "%s\\%s.prn", printer->spoolDir, jobId);
254			fp = fopen(printJob, "ab");
255			if (fp)
256			{
257				fwrite(jobData, 1, dataLen, fp);
258				fclose(fp);
259				return B_OK;
260			}
261
262			return BEOS_EACCES;
263		}
264	}
265
266	return BEOS_ENOENT;
267}
268
269// btPrintJobCommit()
270//
271int btPrintJobCommit(char *printerName, char *jobId)
272{
273	char printJob[B_PATH_NAME_LENGTH];
274	bt_printer *printer = btFindPrinter(printerName);
275
276	if (printer)
277	{
278		sprintf(printJob, "%s\\%s.job", printer->spoolDir, jobId);
279		if (access(printJob, 0) == 0)
280		{
281			WritePrivateProfileString("PrintJob", "Status", "Scheduling...", printJob);
282			return B_OK;
283		}
284	}
285
286	return BEOS_ENOENT;
287}
288