+DEFUN ("mswindows-get-default-printer", Fmswindows_get_default_printer, 0, 0, 0, /*
+Return name of the default printer, as string, on nil if there is no default.
+*/
+ ())
+{
+ return msprinter_default_printer ();
+}
+
+static void
+signal_enum_printer_error (void)
+{
+ invalid_operation ("Error enumerating printers", make_int (GetLastError ()));
+}
+
+DEFUN ("mswindows-printer-list", Fmswindows_printer_list, 0, 0, 0, /*
+Return a list of string names of installed printers.
+If there is a default printer, it is returned as the first element of
+the list. If there is no default printer, the first element of the
+list will be nil. The rest of elements are guaranteed to have string
+values. Return value is nil if there are no printers installed.
+*/
+ ())
+{
+ int have_nt, ok;
+ BYTE *data_buf, dummy_byte;
+ size_t enum_entry_size;
+ DWORD enum_flags, enum_level, bytes_needed, num_printers;
+ struct gcpro gcpro1, gcpro2;
+ Lisp_Object result = Qnil, def_printer = Qnil;
+
+ /* Determine OS flavor, to use the fastest enumeration method available */
+ have_nt = !mswindows_windows9x_p ();
+ enum_flags = PRINTER_ENUM_LOCAL | (have_nt ? PRINTER_ENUM_CONNECTIONS : 0);
+ enum_level = have_nt ? 4 : 5;
+ enum_entry_size = have_nt ? sizeof (PRINTER_INFO_4) : sizeof (PRINTER_INFO_5);
+
+ /* Allocate memory for printer enum structure */
+ ok = EnumPrinters (enum_flags, NULL, enum_level, &dummy_byte, 1,
+ &bytes_needed, &num_printers);
+ if (ok)
+ /* No printers, if just 1 byte is enough */
+ return Qnil;
+
+ if (GetLastError () != ERROR_INSUFFICIENT_BUFFER)
+ signal_enum_printer_error ();
+
+ data_buf = alloca (bytes_needed);
+ ok = EnumPrinters (enum_flags, NULL, enum_level, data_buf, bytes_needed,
+ &bytes_needed, &num_printers);
+ if (!ok)
+ signal_enum_printer_error ();
+
+ if (num_printers == 0)
+ /* Strange but... */
+ return Qnil;
+
+ GCPRO2 (result, def_printer);
+
+ while (num_printers--)
+ {
+ LPCTSTR printer_name;
+ if (have_nt)
+ {
+ PRINTER_INFO_4 *info = (PRINTER_INFO_4*) data_buf;
+ printer_name = info->pPrinterName;
+ }
+ else
+ {
+ PRINTER_INFO_5 *info = (PRINTER_INFO_5*) data_buf;
+ printer_name = info->pPrinterName;
+ }
+ data_buf += enum_entry_size;
+
+ result = Fcons (build_ext_string (printer_name, Qmswindows_tstr),
+ result);
+ }
+
+ def_printer = msprinter_default_printer ();
+ result = Fdelete (def_printer, result);
+ result = Fcons (def_printer, result);
+
+ RETURN_UNGCPRO (result);
+}
+