ReactOS  0.4.13-dev-455-g28ed234
printercache.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 8 -*-
2  * rdesktop: A Remote Desktop Protocol client.
3  * Entrypoint and utility functions
4  * Copyright (C) Matthew Chapman 1999-2005
5  * Copyright (C) Jeroen Meijer 2003
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 
22 /* According to the W2K RDP Printer Redirection WhitePaper, a data
23  * blob is sent to the client after the configuration of the printer
24  * is changed at the server.
25  *
26  * This data blob is saved to the registry. The client returns this
27  * data blob in a new session with the printer announce data.
28  * The data is not interpreted by the client.
29  */
30 
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include "rdesktop.h"
38 
39 static BOOL
40 printercache_mkdir(char *base, char *printer)
41 {
42  char *path;
43 
44  path = (char *) xmalloc(strlen(base) + sizeof("/.rdesktop/rdpdr/") + strlen(printer) + 1);
45 
46  sprintf(path, "%s/.rdesktop", base);
47  if ((mkdir(path, 0700) == -1) && errno != EEXIST)
48  {
49  perror(path);
50  xfree(path);
51  return False;
52  }
53 
54  strcat(path, "/rdpdr");
55  if ((mkdir(path, 0700) == -1) && errno != EEXIST)
56  {
57  perror(path);
58  xfree(path);
59  return False;
60  }
61 
62  strcat(path, "/");
63  strcat(path, printer);
64  if ((mkdir(path, 0700) == -1) && errno != EEXIST)
65  {
66  perror(path);
67  xfree(path);
68  return False;
69  }
70 
71  xfree(path);
72  return True;
73 }
74 
75 static BOOL
77 {
78  char *path;
79  char *home;
80 
81  if (printer == NULL)
82  return False;
83 
84  home = getenv("HOME");
85  if (home == NULL)
86  return False;
87 
88  path = (char *) xmalloc(strlen(home) + sizeof("/.rdesktop/rdpdr/") + strlen(printer) +
89  sizeof("/AutoPrinterCacheData") + 1);
90 
91  sprintf(path, "%s/.rdesktop/rdpdr/%s/AutoPrinterCacheData", home, printer);
92 
93  if (unlink(path) < 0)
94  {
95  xfree(path);
96  return False;
97  }
98 
99  sprintf(path, "%s/.rdesktop/rdpdr/%s", home, printer);
100 
101  if (rmdir(path) < 0)
102  {
103  xfree(path);
104  return False;
105  }
106 
107  xfree(path);
108  return True;
109 }
110 
111 
112 static BOOL
113 printercache_rename_blob(char *printer, char *new_printer)
114 {
115  char *printer_path;
116  char *new_printer_path;
117  int printer_maxlen;
118 
119  char *home;
120 
121  if (printer == NULL)
122  return False;
123 
124  home = getenv("HOME");
125  if (home == NULL)
126  return False;
127 
128  printer_maxlen =
129  (strlen(printer) >
130  strlen(new_printer) ? strlen(printer) : strlen(new_printer)) + strlen(home) +
131  sizeof("/.rdesktop/rdpdr/") + 1;
132 
133  printer_path = (char *) xmalloc(printer_maxlen);
134  new_printer_path = (char *) xmalloc(printer_maxlen);
135 
136  sprintf(printer_path, "%s/.rdesktop/rdpdr/%s", home, printer);
137  sprintf(new_printer_path, "%s/.rdesktop/rdpdr/%s", home, new_printer);
138 
139  printf("%s,%s\n", printer_path, new_printer_path);
140  if (rename(printer_path, new_printer_path) < 0)
141  {
142  xfree(printer_path);
143  xfree(new_printer_path);
144  return False;
145  }
146 
147  xfree(printer_path);
148  xfree(new_printer_path);
149  return True;
150 }
151 
152 
153 int
154 printercache_load_blob(char *printer_name, uint8 ** data)
155 {
156  char *home, *path;
157  struct stat st;
158  int fd, length;
159 
160  if (printer_name == NULL)
161  return 0;
162 
163  *data = NULL;
164 
165  home = getenv("HOME");
166  if (home == NULL)
167  return 0;
168 
169  path = (char *) xmalloc(strlen(home) + sizeof("/.rdesktop/rdpdr/") + strlen(printer_name) +
170  sizeof("/AutoPrinterCacheData") + 1);
171  sprintf(path, "%s/.rdesktop/rdpdr/%s/AutoPrinterCacheData", home, printer_name);
172 
173  fd = open(path, O_RDONLY);
174  if (fd == -1)
175  {
176  xfree(path);
177  return 0;
178  }
179 
180  if (fstat(fd, &st))
181  {
182  xfree(path);
183  close(fd);
184  return 0;
185  }
186 
187  *data = (uint8 *) xmalloc(st.st_size);
188  length = read(fd, *data, st.st_size);
189  close(fd);
190  xfree(path);
191  return length;
192 }
193 
194 static void
196 {
197  char *home, *path;
198  int fd;
199 
200  if (printer_name == NULL)
201  return;
202 
203  home = getenv("HOME");
204  if (home == NULL)
205  return;
206 
207  if (!printercache_mkdir(home, printer_name))
208  return;
209 
210  path = (char *) xmalloc(strlen(home) + sizeof("/.rdesktop/rdpdr/") + strlen(printer_name) +
211  sizeof("/AutoPrinterCacheData") + 1);
212  sprintf(path, "%s/.rdesktop/rdpdr/%s/AutoPrinterCacheData", home, printer_name);
213 
214  fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
215  if (fd == -1)
216  {
217  perror(path);
218  xfree(path);
219  return;
220  }
221 
222  if (write(fd, data, length) != length)
223  {
224  perror(path);
225  unlink(path);
226  }
227 
228  close(fd);
229  xfree(path);
230 }
231 
232 void
234 {
235  uint32 type, printer_length, driver_length, printer_unicode_length, blob_length;
236  char device_name[9], printer[256], driver[256];
237 
238  in_uint32_le(s, type);
239  switch (type)
240  {
241  case 4: /* rename item */
242  in_uint8(s, printer_length);
243  in_uint8s(s, 0x3); /* padding */
244  in_uint8(s, driver_length);
245  in_uint8s(s, 0x3); /* padding */
246 
247  /* NOTE - 'driver' doesn't contain driver, it contains the new printer name */
248 
249  rdp_in_unistr(This, s, printer, printer_length);
250  rdp_in_unistr(This, s, driver, driver_length);
251 
253  break;
254 
255  case 3: /* delete item */
256  in_uint8(s, printer_unicode_length);
257  in_uint8s(s, 0x3); /* padding */
258  printer_length = rdp_in_unistr(This, s, printer, printer_unicode_length);
259  printercache_unlink_blob(printer);
260  break;
261 
262  case 2: /* save printer data */
263  in_uint32_le(s, printer_unicode_length);
264  in_uint32_le(s, blob_length);
265 
266  if (printer_unicode_length < 2 * 255)
267  {
268  rdp_in_unistr(This, s, printer, printer_unicode_length);
269  printercache_save_blob(printer, s->p, blob_length);
270  }
271  break;
272 
273  case 1: /* save device data */
274  in_uint8a(s, device_name, 5); /* get LPTx/COMx name */
275 
276  /* need to fetch this data so that we can get the length of the packet to store. */
277  in_uint8s(s, 0x2); /* ??? */
278  in_uint8s(s, 0x2) /* pad?? */
279  in_uint32_be(s, driver_length);
280  in_uint32_be(s, printer_length);
281  in_uint8s(s, 0x7) /* pad?? */
282  /* next is driver in unicode */
283  /* next is printer in unicode */
284  /* TODO: figure out how to use this information when reconnecting */
285  /* actually - all we need to store is the driver and printer */
286  /* and figure out what the first word is. */
287  /* rewind stream so that we can save this blob */
288  /* length is driver_length + printer_length + 19 */
289  /* rewind stream */
290  s->p = s->p - 19;
291 
293  driver_length + printer_length + 19);
294  break;
295  default:
296 
297  unimpl("RDPDR Printer Cache Packet Type: %d\n", type);
298  break;
299  }
300 }
void rdp_in_unistr(STREAM s, int in_len, char **string, uint32 *str_size)
Definition: rdp.c:265
void printercache_process(RDPCLIENT *This, STREAM s)
Definition: printercache.c:233
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
#define open
Definition: acwin.h:71
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLsizei const GLchar ** path
Definition: glext.h:7234
unsigned int uint32
Definition: types.h:32
static const WCHAR device_name[]
Definition: btrfs.c:55
#define unlink
Definition: syshdrs.h:54
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
int printercache_load_blob(char *printer_name, uint8 **data)
Definition: printercache.c:154
static int fd
Definition: io.c:51
int errno
static BOOL printercache_mkdir(char *base, char *printer)
Definition: printercache.c:40
#define EEXIST
Definition: acclib.h:88
static BOOL printercache_rename_blob(char *printer, char *new_printer)
Definition: printercache.c:113
static BOOL printercache_unlink_blob(char *printer)
Definition: printercache.c:76
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define write
Definition: acwin.h:73
_Check_return_ int __cdecl rename(_In_z_ const char *_OldFilename, _In_z_ const char *_NewFilename)
void * xmalloc(int size)
Definition: uimain.c:747
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
unsigned int BOOL
Definition: ntddk_ex.h:94
#define O_WRONLY
Definition: acwin.h:85
struct @1600::@1601 driver
smooth NULL
Definition: ftsmooth.c:416
#define in_uint32_be(s, v)
Definition: parse.h:76
#define in_uint8s(s, n)
Definition: parse.h:91
#define True
Definition: types.h:24
#define False
Definition: types.h:25
void xfree(void *mem)
Definition: uimain.c:758
#define mkdir
Definition: acwin.h:77
Definition: tftpd.h:37
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static void printercache_save_blob(char *printer_name, uint8 *data, uint32 length)
Definition: printercache.c:195
unsigned char uint8
Definition: types.h:28
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
Definition: parse.h:22
char home[]
Definition: main.c:47
Definition: stat.h:55
GLdouble s
Definition: gl.h:2039
#define O_TRUNC
Definition: acwin.h:86
#define close
Definition: acwin.h:74
#define in_uint8a(s, v, n)
Definition: parse.h:90
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
Definition: services.c:325
#define in_uint8(s, v)
Definition: parse.h:88
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3706
_CRTIMP int __cdecl fstat(int _Desc, struct stat *_Stat)
Definition: stat.h:341
void unimpl(char *format,...)
Definition: uimain.c:801
#define in_uint32_le(s, v)
Definition: parse.h:56
#define rmdir
Definition: syshdrs.h:70
#define O_CREAT
Definition: acwin.h:84
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
_off_t st_size
Definition: stat.h:63
#define printf
Definition: config.h:203
#define O_RDONLY
Definition: acwin.h:82