2c0b816f437e89083b5d09ba18b5850bcefe42c4
[platform/upstream/dbus.git] / dbus / dbus-sysdeps-util-win.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-sysdeps-util.c Would be in dbus-sysdeps.c, but not used in libdbus
3  * 
4  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat, Inc.
5  * Copyright (C) 2003 CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #undef open
26
27 #define STRSAFE_NO_DEPRECATE
28
29 #include "dbus-sysdeps.h"
30 #include "dbus-internals.h"
31 #include "dbus-protocol.h"
32 #include "dbus-string.h"
33 #include "dbus-sysdeps.h"
34 #include "dbus-sysdeps-win.h"
35 #include "dbus-sockets-win.h"
36 #include "dbus-memory.h"
37
38 #include <io.h>
39 #include <sys/stat.h>
40 #include <aclapi.h>
41 #include <winsock2.h>
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <fcntl.h>
46 #include <errno.h>
47 #include <winsock2.h>   // WSA error codes
48
49 #if defined __MINGW32__ || (defined _MSC_VER && _MSC_VER <= 1310)
50 /* save string functions version
51    using DBusString needs to much time because of uncommon api 
52 */ 
53 #define errno_t int
54
55 errno_t strcat_s(char *dest, size_t size, char *src) 
56 {
57   _dbus_assert(strlen(dest) + strlen(src) +1 <= size);
58   strcat(dest,src);
59   return 0;
60 }
61
62 errno_t strcpy_s(char *dest, size_t size, char *src)
63 {
64   _dbus_assert(strlen(src) +1 <= size);
65   strcpy(dest,src);  
66   return 0;
67 }
68 #endif
69
70 /**
71  * Does the chdir, fork, setsid, etc. to become a daemon process.
72  *
73  * @param pidfile #NULL, or pidfile to create
74  * @param print_pid_fd file descriptor to print daemon's pid to, or -1 for none
75  * @param error return location for errors
76  * @param keep_umask #TRUE to keep the original umask
77  * @returns #FALSE on failure
78  */
79 dbus_bool_t
80 _dbus_become_daemon (const DBusString *pidfile,
81                      DBusPipe         *print_pid_pipe,
82                      DBusError        *error,
83                      dbus_bool_t       keep_umask)
84 {
85   return TRUE;
86 }
87
88 /**
89  * Creates a file containing the process ID.
90  *
91  * @param filename the filename to write to
92  * @param pid our process ID
93  * @param error return location for errors
94  * @returns #FALSE on failure
95  */
96 dbus_bool_t
97 _dbus_write_pid_file (const DBusString *filename,
98                       unsigned long     pid,
99                       DBusError        *error)
100 {
101   const char *cfilename;
102   int fd;
103   FILE *f;
104
105   cfilename = _dbus_string_get_const_data (filename);
106   
107   fd = _open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
108   
109   if (fd < 0)
110     {
111       dbus_set_error (error, _dbus_error_from_errno (errno),
112                       "Failed to open \"%s\": %s", cfilename,
113                       strerror (errno));
114       return FALSE;
115     }
116
117   if ((f = fdopen (fd, "w")) == NULL)
118     {
119       dbus_set_error (error, _dbus_error_from_errno (errno),
120                       "Failed to fdopen fd %d: %s", fd, strerror (errno));
121       _close (fd);
122       return FALSE;
123     }
124
125   if (fprintf (f, "%lu\n", pid) < 0)
126     {
127       dbus_set_error (error, _dbus_error_from_errno (errno),
128                       "Failed to write to \"%s\": %s", cfilename,
129                       strerror (errno));
130
131       fclose (f);
132       return FALSE;
133     }
134
135   if (fclose (f) == EOF)
136     {
137       dbus_set_error (error, _dbus_error_from_errno (errno),
138                       "Failed to close \"%s\": %s", cfilename,
139                       strerror (errno));
140       return FALSE;
141     }
142
143   return TRUE;
144 }
145
146 /**
147  * Writes the given pid_to_write to a pidfile (if non-NULL) and/or to a
148  * pipe (if non-NULL). Does nothing if pidfile and print_pid_pipe are both
149  * NULL.
150  *
151  * @param pidfile the file to write to or #NULL
152  * @param print_pid_pipe the pipe to write to or #NULL
153  * @param pid_to_write the pid to write out
154  * @param error error on failure
155  * @returns FALSE if error is set
156  */
157 dbus_bool_t
158 _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile,
159                                   DBusPipe         *print_pid_pipe,
160                                   dbus_pid_t        pid_to_write,
161                                   DBusError        *error)
162 {
163   if (pidfile)
164     {
165       _dbus_verbose ("writing pid file %s\n", _dbus_string_get_const_data (pidfile));
166       if (!_dbus_write_pid_file (pidfile,
167                                  pid_to_write,
168                                  error))
169         {
170           _dbus_verbose ("pid file write failed\n");
171           _DBUS_ASSERT_ERROR_IS_SET(error);
172           return FALSE;
173         }
174     }
175   else
176     {
177       _dbus_verbose ("No pid file requested\n");
178     }
179
180   if (print_pid_pipe != NULL && _dbus_pipe_is_valid (print_pid_pipe))
181     {
182       DBusString pid;
183       int bytes;
184
185       _dbus_verbose ("writing our pid to pipe %d\n", print_pid_pipe->fd_or_handle);
186
187       if (!_dbus_string_init (&pid))
188         {
189           _DBUS_SET_OOM (error);
190           return FALSE;
191         }
192
193       if (!_dbus_string_append_int (&pid, pid_to_write) ||
194           !_dbus_string_append (&pid, "\n"))
195         {
196           _dbus_string_free (&pid);
197           _DBUS_SET_OOM (error);
198           return FALSE;
199         }
200
201       bytes = _dbus_string_get_length (&pid);
202       if (_dbus_pipe_write (print_pid_pipe, &pid, 0, bytes, error) != bytes)
203         {
204           /* _dbus_pipe_write sets error only on failure, not short write */
205           if (error != NULL && !dbus_error_is_set(error))
206             {
207               dbus_set_error (error, DBUS_ERROR_FAILED,
208                               "Printing message bus PID: did not write enough bytes\n");
209             }
210           _dbus_string_free (&pid);
211           return FALSE;
212         }
213
214       _dbus_string_free (&pid);
215     }
216   else
217     {
218       _dbus_verbose ("No pid pipe to write to\n");
219     }
220
221   return TRUE;
222 }
223
224 /**
225  * Verify that after the fork we can successfully change to this user.
226  *
227  * @param user the username given in the daemon configuration
228  * @returns #TRUE if username is valid
229  */
230 dbus_bool_t
231 _dbus_verify_daemon_user (const char *user)
232 {
233   return TRUE;
234 }
235
236 /**
237  * Changes the user and group the bus is running as.
238  *
239  * @param user the user to become
240  * @param error return location for errors
241  * @returns #FALSE on failure
242  */
243 dbus_bool_t
244 _dbus_change_to_daemon_user  (const char    *user,
245                               DBusError     *error)
246 {
247   return TRUE;
248 }
249
250 /**
251  * Changes the user and group the bus is running as.
252  *
253  * @param uid the new user ID
254  * @param gid the new group ID
255  * @param error return location for errors
256  * @returns #FALSE on failure
257  */
258 dbus_bool_t
259 _dbus_change_identity  (dbus_uid_t     uid,
260                         dbus_gid_t     gid,
261                         DBusError     *error)
262 {
263   return TRUE;
264 }
265
266 /** Checks if user is at the console
267 *
268 * @param username user to check
269 * @param error return location for errors
270 * @returns #TRUE is the user is at the consolei and there are no errors
271 */
272 dbus_bool_t
273 _dbus_user_at_console(const char *username,
274                       DBusError  *error)
275 {
276 #ifdef DBUS_WINCE
277         return TRUE;
278 #else
279   dbus_bool_t retval = FALSE;
280   wchar_t *wusername;
281   DWORD sid_length;
282   PSID user_sid, console_user_sid;
283   HWINSTA winsta;
284
285   wusername = _dbus_win_utf8_to_utf16 (username, error);
286   if (!wusername)
287     return FALSE;
288
289   // TODO remove
290   if (!_dbus_win_account_to_sid (wusername, &user_sid, error))
291     goto out0;
292
293   /* Now we have the SID for username. Get the SID of the
294    * user at the "console" (window station WinSta0)
295    */
296   if (!(winsta = OpenWindowStation ("WinSta0", FALSE, READ_CONTROL)))
297     {
298       _dbus_win_set_error_from_win_error (error, GetLastError ());
299       goto out2;
300     }
301
302   sid_length = 0;
303   GetUserObjectInformation (winsta, UOI_USER_SID,
304                             NULL, 0, &sid_length);
305   if (sid_length == 0)
306     {
307       /* Nobody is logged on */
308       goto out2;
309     }
310
311   if (sid_length < 0 || sid_length > 1000)
312     {
313       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID length");
314       goto out3;
315     }
316
317   console_user_sid = dbus_malloc (sid_length);
318   if (!console_user_sid)
319     {
320       _DBUS_SET_OOM (error);
321       goto out3;
322     }
323
324   if (!GetUserObjectInformation (winsta, UOI_USER_SID,
325                                  console_user_sid, sid_length, &sid_length))
326     {
327       _dbus_win_set_error_from_win_error (error, GetLastError ());
328       goto out4;
329     }
330
331   if (!IsValidSid (console_user_sid))
332     {
333       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
334       goto out4;
335     }
336
337   retval = EqualSid (user_sid, console_user_sid);
338
339 out4:
340   dbus_free (console_user_sid);
341 out3:
342   CloseWindowStation (winsta);
343 out2:
344   dbus_free (user_sid);
345 out0:
346   dbus_free (wusername);
347
348   return retval;
349 #endif //DBUS_WINCE
350 }
351
352 /**
353  * Removes a directory; Directory must be empty
354  * 
355  * @param filename directory filename
356  * @param error initialized error object
357  * @returns #TRUE on success
358  */
359 dbus_bool_t
360 _dbus_delete_directory (const DBusString *filename,
361                         DBusError        *error)
362 {
363   const char *filename_c;
364
365   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
366
367   filename_c = _dbus_string_get_const_data (filename);
368
369   if (_rmdir (filename_c) != 0)
370     {
371       dbus_set_error (error, DBUS_ERROR_FAILED,
372                       "Failed to remove directory %s: %s\n",
373                       filename_c, strerror (errno));
374       return FALSE;
375     }
376
377   return TRUE;
378 }
379
380 void
381 _dbus_init_system_log (void)
382 {
383     // FIXME!
384 }
385
386 /**
387  * Log an informative message.  Intended for use primarily by
388  * the system bus.
389  *
390  * @param msg a printf-style format string
391  * @param args arguments for the format string
392  */
393 void
394 _dbus_log_info (const char *msg, va_list args)
395 {
396     // FIXME!
397 }
398
399 /**
400  * Log a security-related message.  Intended for use primarily by
401  * the system bus.
402  *
403  * @param msg a printf-style format string
404  * @param args arguments for the format string
405  */
406 void
407 _dbus_log_security (const char *msg, va_list args)
408 {
409     // FIXME!
410 }
411
412 /** Installs a signal handler
413  *
414  * @param sig the signal to handle
415  * @param handler the handler
416  */
417 void
418 _dbus_set_signal_handler (int               sig,
419                           DBusSignalHandler handler)
420 {
421   _dbus_verbose ("_dbus_set_signal_handler() has to be implemented\n");
422 }
423
424 /** Checks if a file exists
425 *
426 * @param file full path to the file
427 * @returns #TRUE if file exists
428 */
429 dbus_bool_t 
430 _dbus_file_exists (const char *file)
431 {
432   HANDLE h = CreateFile(
433           file, /* LPCTSTR lpFileName*/
434           0, /* DWORD dwDesiredAccess */
435           0, /* DWORD dwShareMode*/
436           NULL, /* LPSECURITY_ATTRIBUTES lpSecurityAttributes */
437           OPEN_EXISTING, /* DWORD dwCreationDisposition */
438           FILE_ATTRIBUTE_NORMAL, /* DWORD dwFlagsAndAttributes */
439           NULL /* HANDLE hTemplateFile */
440         );
441
442     /* file not found, use local copy of session.conf  */
443     if (h != INVALID_HANDLE_VALUE && GetLastError() != ERROR_PATH_NOT_FOUND)
444       {
445         CloseHandle(h);
446         return TRUE;
447       }
448     else
449         return FALSE;  
450 }
451
452 /**
453  * stat() wrapper.
454  *
455  * @param filename the filename to stat
456  * @param statbuf the stat info to fill in
457  * @param error return location for error
458  * @returns #FALSE if error was set
459  */
460 dbus_bool_t
461 _dbus_stat(const DBusString *filename,
462            DBusStat         *statbuf,
463            DBusError        *error)
464 {
465 #ifdef DBUS_WINCE
466         return TRUE;
467         //TODO
468 #else
469   const char *filename_c;
470   WIN32_FILE_ATTRIBUTE_DATA wfad;
471   char *lastdot;
472   DWORD rc;
473   PSID owner_sid, group_sid;
474   PSECURITY_DESCRIPTOR sd;
475
476   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
477
478   filename_c = _dbus_string_get_const_data (filename);
479
480   if (!GetFileAttributesEx (filename_c, GetFileExInfoStandard, &wfad))
481     {
482       _dbus_win_set_error_from_win_error (error, GetLastError ());
483       return FALSE;
484     }
485
486   if (wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
487     statbuf->mode = _S_IFDIR;
488   else
489     statbuf->mode = _S_IFREG;
490
491   statbuf->mode |= _S_IREAD;
492   if (wfad.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
493     statbuf->mode |= _S_IWRITE;
494
495   lastdot = strrchr (filename_c, '.');
496   if (lastdot && stricmp (lastdot, ".exe") == 0)
497     statbuf->mode |= _S_IEXEC;
498
499   statbuf->mode |= (statbuf->mode & 0700) >> 3;
500   statbuf->mode |= (statbuf->mode & 0700) >> 6;
501
502   statbuf->nlink = 1;
503
504   sd = NULL;
505   rc = GetNamedSecurityInfo ((char *) filename_c, SE_FILE_OBJECT,
506                              OWNER_SECURITY_INFORMATION |
507                              GROUP_SECURITY_INFORMATION,
508                              &owner_sid, &group_sid,
509                              NULL, NULL,
510                              &sd);
511   if (rc != ERROR_SUCCESS)
512     {
513       _dbus_win_set_error_from_win_error (error, rc);
514       if (sd != NULL)
515         LocalFree (sd);
516       return FALSE;
517     }
518
519 #ifdef ENABLE_UID_TO_SID
520   /* FIXME */
521   statbuf->uid = _dbus_win_sid_to_uid_t (owner_sid);
522   statbuf->gid = _dbus_win_sid_to_uid_t (group_sid);
523 #endif
524
525   LocalFree (sd);
526
527   statbuf->size = ((dbus_int64_t) wfad.nFileSizeHigh << 32) + wfad.nFileSizeLow;
528
529   statbuf->atime =
530     (((dbus_int64_t) wfad.ftLastAccessTime.dwHighDateTime << 32) +
531      wfad.ftLastAccessTime.dwLowDateTime) / 10000000 - DBUS_INT64_CONSTANT (116444736000000000);
532
533   statbuf->mtime =
534     (((dbus_int64_t) wfad.ftLastWriteTime.dwHighDateTime << 32) +
535      wfad.ftLastWriteTime.dwLowDateTime) / 10000000 - DBUS_INT64_CONSTANT (116444736000000000);
536
537   statbuf->ctime =
538     (((dbus_int64_t) wfad.ftCreationTime.dwHighDateTime << 32) +
539      wfad.ftCreationTime.dwLowDateTime) / 10000000 - DBUS_INT64_CONSTANT (116444736000000000);
540
541   return TRUE;
542 #endif //DBUS_WINCE
543 }
544
545
546 #ifdef HAVE_DIRENT_H
547
548 // mingw ships with dirent.h
549 #include <dirent.h>
550 #define _dbus_opendir opendir
551 #define _dbus_readdir readdir
552 #define _dbus_closedir closedir
553
554 #else
555
556 #ifdef HAVE_IO_H
557 #include <io.h> // win32 file functions
558 #endif
559
560 #include <sys/types.h>
561 #include <stdlib.h>
562
563 /* This file is part of the KDE project
564 Copyright (C) 2000 Werner Almesberger
565
566 libc/sys/linux/sys/dirent.h - Directory entry as returned by readdir
567
568 This program is free software; you can redistribute it and/or
569 modify it under the terms of the GNU Library General Public
570 License as published by the Free Software Foundation; either
571 version 2 of the License, or (at your option) any later version.
572
573 This program is distributed in the hope that it will be useful,
574 but WITHOUT ANY WARRANTY; without even the implied warranty of
575 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
576 Library General Public License for more details.
577
578 You should have received a copy of the GNU Library General Public License
579 along with this program; see the file COPYING.  If not, write to
580 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
581 Boston, MA 02110-1301, USA.
582 */
583 #define HAVE_NO_D_NAMLEN        /* no struct dirent->d_namlen */
584 #define HAVE_DD_LOCK            /* have locking mechanism */
585
586 #define MAXNAMLEN 255           /* sizeof(struct dirent.d_name)-1 */
587
588 #define __dirfd(dir) (dir)->dd_fd
589
590 /* struct dirent - same as Unix */
591 struct dirent
592   {
593     long d_ino;                    /* inode (always 1 in WIN32) */
594     off_t d_off;                /* offset to this dirent */
595     unsigned short d_reclen;    /* length of d_name */
596     char d_name[_MAX_FNAME+1];    /* filename (null terminated) */
597   };
598
599 /* typedef DIR - not the same as Unix */
600 typedef struct
601   {
602     long handle;                /* _findfirst/_findnext handle */
603     short offset;                /* offset into directory */
604     short finished;             /* 1 if there are not more files */
605     struct _finddata_t fileinfo;  /* from _findfirst/_findnext */
606     char *dir;                  /* the dir we are reading */
607     struct dirent dent;         /* the dirent to return */
608   }
609 DIR;
610
611 /**********************************************************************
612 * Implement dirent-style opendir/readdir/closedir on Window 95/NT
613 *
614 * Functions defined are opendir(), readdir() and closedir() with the
615 * same prototypes as the normal dirent.h implementation.
616 *
617 * Does not implement telldir(), seekdir(), rewinddir() or scandir().
618 * The dirent struct is compatible with Unix, except that d_ino is
619 * always 1 and d_off is made up as we go along.
620 *
621 * The DIR typedef is not compatible with Unix.
622 **********************************************************************/
623
624 DIR * _dbus_opendir(const char *dir)
625 {
626   DIR *dp;
627   char *filespec;
628   long handle;
629   int index;
630
631   filespec = malloc(strlen(dir) + 2 + 1);
632   strcpy(filespec, dir);
633   index = strlen(filespec) - 1;
634   if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
635     filespec[index] = '\0';
636   strcat(filespec, "\\*");
637
638   dp = (DIR *)malloc(sizeof(DIR));
639   dp->offset = 0;
640   dp->finished = 0;
641   dp->dir = strdup(dir);
642
643   if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0)
644     {
645       if (errno == ENOENT)
646         dp->finished = 1;
647       else
648         return NULL;
649     }
650
651   dp->handle = handle;
652   free(filespec);
653
654   return dp;
655 }
656
657 struct dirent * _dbus_readdir(DIR *dp)
658   {
659     if (!dp || dp->finished)
660       return NULL;
661
662     if (dp->offset != 0)
663       {
664         if (_findnext(dp->handle, &(dp->fileinfo)) < 0)
665           {
666             dp->finished = 1;
667             errno = 0;
668             return NULL;
669           }
670       }
671     dp->offset++;
672
673     strncpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME);
674     dp->dent.d_ino = 1;
675     dp->dent.d_reclen = strlen(dp->dent.d_name);
676     dp->dent.d_off = dp->offset;
677
678     return &(dp->dent);
679   }
680
681
682 int _dbus_closedir(DIR *dp)
683 {
684   if (!dp)
685     return 0;
686   _findclose(dp->handle);
687   if (dp->dir)
688     free(dp->dir);
689   if (dp)
690     free(dp);
691
692   return 0;
693 }
694
695 #endif //#ifdef HAVE_DIRENT_H
696
697 /**
698  * Internals of directory iterator
699  */
700 struct DBusDirIter
701   {
702     DIR *d; /**< The DIR* from opendir() */
703
704   };
705
706 /**
707  * Open a directory to iterate over.
708  *
709  * @param filename the directory name
710  * @param error exception return object or #NULL
711  * @returns new iterator, or #NULL on error
712  */
713 DBusDirIter*
714 _dbus_directory_open (const DBusString *filename,
715                       DBusError        *error)
716 {
717   DIR *d;
718   DBusDirIter *iter;
719   const char *filename_c;
720
721   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
722
723   filename_c = _dbus_string_get_const_data (filename);
724
725   d = _dbus_opendir (filename_c);
726   if (d == NULL)
727     {
728       dbus_set_error (error, _dbus_error_from_errno (errno),
729                       "Failed to read directory \"%s\": %s",
730                       filename_c,
731                       _dbus_strerror (errno));
732       return NULL;
733     }
734   iter = dbus_new0 (DBusDirIter, 1);
735   if (iter == NULL)
736     {
737       _dbus_closedir (d);
738       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
739                       "Could not allocate memory for directory iterator");
740       return NULL;
741     }
742
743   iter->d = d;
744
745   return iter;
746 }
747
748 /**
749  * Get next file in the directory. Will not return "." or ".."  on
750  * UNIX. If an error occurs, the contents of "filename" are
751  * undefined. The error is never set if the function succeeds.
752  *
753  * @todo for thread safety, I think we have to use
754  * readdir_r(). (GLib has the same issue, should file a bug.)
755  *
756  * @param iter the iterator
757  * @param filename string to be set to the next file in the dir
758  * @param error return location for error
759  * @returns #TRUE if filename was filled in with a new filename
760  */
761 dbus_bool_t
762 _dbus_directory_get_next_file (DBusDirIter      *iter,
763                                DBusString       *filename,
764                                DBusError        *error)
765 {
766   struct dirent *ent;
767
768   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
769
770 again:
771   errno = 0;
772   ent = _dbus_readdir (iter->d);
773   if (ent == NULL)
774     {
775       if (errno != 0)
776         dbus_set_error (error,
777                         _dbus_error_from_errno (errno),
778                         "%s", _dbus_strerror (errno));
779       return FALSE;
780     }
781   else if (ent->d_name[0] == '.' &&
782            (ent->d_name[1] == '\0' ||
783             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
784     goto again;
785   else
786     {
787       _dbus_string_set_length (filename, 0);
788       if (!_dbus_string_append (filename, ent->d_name))
789         {
790           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
791                           "No memory to read directory entry");
792           return FALSE;
793         }
794       else
795         return TRUE;
796     }
797 }
798
799 /**
800  * Closes a directory iteration.
801  */
802 void
803 _dbus_directory_close (DBusDirIter *iter)
804 {
805   _dbus_closedir (iter->d);
806   dbus_free (iter);
807 }
808
809 /**
810  * Checks whether the filename is an absolute path
811  *
812  * @param filename the filename
813  * @returns #TRUE if an absolute path
814  */
815 dbus_bool_t
816 _dbus_path_is_absolute (const DBusString *filename)
817 {
818   if (_dbus_string_get_length (filename) > 0)
819     return _dbus_string_get_byte (filename, 1) == ':'
820            || _dbus_string_get_byte (filename, 0) == '\\'
821            || _dbus_string_get_byte (filename, 0) == '/';
822   else
823     return FALSE;
824 }
825
826 /** @} */ /* End of DBusInternalsUtils functions */
827
828 /**
829  * @addtogroup DBusString
830  *
831  * @{
832  */
833 /**
834  * Get the directory name from a complete filename
835  * @param filename the filename
836  * @param dirname string to append directory name to
837  * @returns #FALSE if no memory
838  */
839 dbus_bool_t
840 _dbus_string_get_dirname(const DBusString *filename,
841                          DBusString       *dirname)
842 {
843   int sep;
844
845   _dbus_assert (filename != dirname);
846   _dbus_assert (filename != NULL);
847   _dbus_assert (dirname != NULL);
848
849   /* Ignore any separators on the end */
850   sep = _dbus_string_get_length (filename);
851   if (sep == 0)
852     return _dbus_string_append (dirname, "."); /* empty string passed in */
853
854   while (sep > 0 &&
855          (_dbus_string_get_byte (filename, sep - 1) == '/' ||
856           _dbus_string_get_byte (filename, sep - 1) == '\\'))
857     --sep;
858
859   _dbus_assert (sep >= 0);
860
861   if (sep == 0 ||
862       (sep == 2 &&
863        _dbus_string_get_byte (filename, 1) == ':' &&
864        isalpha (_dbus_string_get_byte (filename, 0))))
865     return _dbus_string_copy_len (filename, 0, sep + 1,
866                                   dirname, _dbus_string_get_length (dirname));
867
868   {
869     int sep1, sep2;
870     _dbus_string_find_byte_backward (filename, sep, '/', &sep1);
871     _dbus_string_find_byte_backward (filename, sep, '\\', &sep2);
872
873     sep = MAX (sep1, sep2);
874   }
875   if (sep < 0)
876     return _dbus_string_append (dirname, ".");
877
878   while (sep > 0 &&
879          (_dbus_string_get_byte (filename, sep - 1) == '/' ||
880           _dbus_string_get_byte (filename, sep - 1) == '\\'))
881     --sep;
882
883   _dbus_assert (sep >= 0);
884
885   if ((sep == 0 ||
886        (sep == 2 &&
887         _dbus_string_get_byte (filename, 1) == ':' &&
888         isalpha (_dbus_string_get_byte (filename, 0))))
889       &&
890       (_dbus_string_get_byte (filename, sep) == '/' ||
891        _dbus_string_get_byte (filename, sep) == '\\'))
892     return _dbus_string_copy_len (filename, 0, sep + 1,
893                                   dirname, _dbus_string_get_length (dirname));
894   else
895     return _dbus_string_copy_len (filename, 0, sep - 0,
896                                   dirname, _dbus_string_get_length (dirname));
897 }
898
899
900 /**
901  * Checks to see if the UNIX user ID matches the UID of
902  * the process. Should always return #FALSE on Windows.
903  *
904  * @param uid the UNIX user ID
905  * @returns #TRUE if this uid owns the process.
906  */
907 dbus_bool_t
908 _dbus_unix_user_is_process_owner (dbus_uid_t uid)
909 {
910   return FALSE;
911 }
912
913 /*=====================================================================
914   unix emulation functions - should be removed sometime in the future
915  =====================================================================*/
916
917 /**
918  * Checks to see if the UNIX user ID is at the console.
919  * Should always fail on Windows (set the error to
920  * #DBUS_ERROR_NOT_SUPPORTED).
921  *
922  * @param uid UID of person to check 
923  * @param error return location for errors
924  * @returns #TRUE if the UID is the same as the console user and there are no errors
925  */
926 dbus_bool_t
927 _dbus_unix_user_is_at_console (dbus_uid_t         uid,
928                                DBusError         *error)
929 {
930   return FALSE;
931 }
932
933
934 /**
935  * Parse a UNIX group from the bus config file. On Windows, this should
936  * simply always fail (just return #FALSE).
937  *
938  * @param groupname the groupname text
939  * @param gid_p place to return the gid
940  * @returns #TRUE on success
941  */
942 dbus_bool_t
943 _dbus_parse_unix_group_from_config (const DBusString  *groupname,
944                                     dbus_gid_t        *gid_p)
945 {
946   return FALSE;
947 }
948
949 /**
950  * Parse a UNIX user from the bus config file. On Windows, this should
951  * simply always fail (just return #FALSE).
952  *
953  * @param username the username text
954  * @param uid_p place to return the uid
955  * @returns #TRUE on success
956  */
957 dbus_bool_t
958 _dbus_parse_unix_user_from_config (const DBusString  *username,
959                                    dbus_uid_t        *uid_p)
960 {
961   return FALSE;
962 }
963
964
965 /**
966  * Gets all groups corresponding to the given UNIX user ID. On UNIX,
967  * just calls _dbus_groups_from_uid(). On Windows, should always
968  * fail since we don't know any UNIX groups.
969  *
970  * @param uid the UID
971  * @param group_ids return location for array of group IDs
972  * @param n_group_ids return location for length of returned array
973  * @returns #TRUE if the UID existed and we got some credentials
974  */
975 dbus_bool_t
976 _dbus_unix_groups_from_uid (dbus_uid_t            uid,
977                             dbus_gid_t          **group_ids,
978                             int                  *n_group_ids)
979 {
980   return FALSE;
981 }
982
983
984
985 /** @} */ /* DBusString stuff */
986
987 /************************************************************************
988  
989  error handling
990  
991  ************************************************************************/
992
993
994 /**
995  * Assigns an error name and message corresponding to a Win32 error
996  * code to a DBusError. Does nothing if error is #NULL.
997  *
998  * @param error the error.
999  * @param code the Win32 error code
1000  */
1001 void
1002 _dbus_win_set_error_from_win_error (DBusError *error,
1003                                     int        code)
1004 {
1005   char *msg;
1006
1007   /* As we want the English message, use the A API */
1008   FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
1009                   FORMAT_MESSAGE_IGNORE_INSERTS |
1010                   FORMAT_MESSAGE_FROM_SYSTEM,
1011                   NULL, code, MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
1012                   (LPTSTR) &msg, 0, NULL);
1013   if (msg)
1014     {
1015       char *msg_copy;
1016
1017       msg_copy = dbus_malloc (strlen (msg));
1018       strcpy (msg_copy, msg);
1019       LocalFree (msg);
1020
1021       dbus_set_error (error, "win32.error", "%s", msg_copy);
1022     }
1023   else
1024     dbus_set_error (error, "win32.error", "Unknown error code %d or FormatMessage failed", code);
1025 }
1026
1027 void
1028 _dbus_win_warn_win_error (const char *message,
1029                           int         code)
1030 {
1031   DBusError error;
1032
1033   dbus_error_init (&error);
1034   _dbus_win_set_error_from_win_error (&error, code);
1035   _dbus_warn ("%s: %s\n", message, error.message);
1036   dbus_error_free (&error);
1037 }
1038
1039 /**
1040  * A wrapper around strerror() because some platforms
1041  * may be lame and not have strerror().
1042  *
1043  * @param error_number errno.
1044  * @returns error description.
1045  */
1046 const char*
1047 _dbus_strerror (int error_number)
1048 {
1049 #ifdef DBUS_WINCE
1050   // TODO
1051   return "unknown";
1052 #else
1053   const char *msg;
1054
1055   switch (error_number)
1056     {
1057     case WSAEINTR:
1058       return "Interrupted function call";
1059     case WSAEACCES:
1060       return "Permission denied";
1061     case WSAEFAULT:
1062       return "Bad address";
1063     case WSAEINVAL:
1064       return "Invalid argument";
1065     case WSAEMFILE:
1066       return "Too many open files";
1067     case WSAEWOULDBLOCK:
1068       return "Resource temporarily unavailable";
1069     case WSAEINPROGRESS:
1070       return "Operation now in progress";
1071     case WSAEALREADY:
1072       return "Operation already in progress";
1073     case WSAENOTSOCK:
1074       return "Socket operation on nonsocket";
1075     case WSAEDESTADDRREQ:
1076       return "Destination address required";
1077     case WSAEMSGSIZE:
1078       return "Message too long";
1079     case WSAEPROTOTYPE:
1080       return "Protocol wrong type for socket";
1081     case WSAENOPROTOOPT:
1082       return "Bad protocol option";
1083     case WSAEPROTONOSUPPORT:
1084       return "Protocol not supported";
1085     case WSAESOCKTNOSUPPORT:
1086       return "Socket type not supported";
1087     case WSAEOPNOTSUPP:
1088       return "Operation not supported";
1089     case WSAEPFNOSUPPORT:
1090       return "Protocol family not supported";
1091     case WSAEAFNOSUPPORT:
1092       return "Address family not supported by protocol family";
1093     case WSAEADDRINUSE:
1094       return "Address already in use";
1095     case WSAEADDRNOTAVAIL:
1096       return "Cannot assign requested address";
1097     case WSAENETDOWN:
1098       return "Network is down";
1099     case WSAENETUNREACH:
1100       return "Network is unreachable";
1101     case WSAENETRESET:
1102       return "Network dropped connection on reset";
1103     case WSAECONNABORTED:
1104       return "Software caused connection abort";
1105     case WSAECONNRESET:
1106       return "Connection reset by peer";
1107     case WSAENOBUFS:
1108       return "No buffer space available";
1109     case WSAEISCONN:
1110       return "Socket is already connected";
1111     case WSAENOTCONN:
1112       return "Socket is not connected";
1113     case WSAESHUTDOWN:
1114       return "Cannot send after socket shutdown";
1115     case WSAETIMEDOUT:
1116       return "Connection timed out";
1117     case WSAECONNREFUSED:
1118       return "Connection refused";
1119     case WSAEHOSTDOWN:
1120       return "Host is down";
1121     case WSAEHOSTUNREACH:
1122       return "No route to host";
1123     case WSAEPROCLIM:
1124       return "Too many processes";
1125     case WSAEDISCON:
1126       return "Graceful shutdown in progress";
1127     case WSATYPE_NOT_FOUND:
1128       return "Class type not found";
1129     case WSAHOST_NOT_FOUND:
1130       return "Host not found";
1131     case WSATRY_AGAIN:
1132       return "Nonauthoritative host not found";
1133     case WSANO_RECOVERY:
1134       return "This is a nonrecoverable error";
1135     case WSANO_DATA:
1136       return "Valid name, no data record of requested type";
1137     case WSA_INVALID_HANDLE:
1138       return "Specified event object handle is invalid";
1139     case WSA_INVALID_PARAMETER:
1140       return "One or more parameters are invalid";
1141     case WSA_IO_INCOMPLETE:
1142       return "Overlapped I/O event object not in signaled state";
1143     case WSA_IO_PENDING:
1144       return "Overlapped operations will complete later";
1145     case WSA_NOT_ENOUGH_MEMORY:
1146       return "Insufficient memory available";
1147     case WSA_OPERATION_ABORTED:
1148       return "Overlapped operation aborted";
1149 #ifdef WSAINVALIDPROCTABLE
1150
1151     case WSAINVALIDPROCTABLE:
1152       return "Invalid procedure table from service provider";
1153 #endif
1154 #ifdef WSAINVALIDPROVIDER
1155
1156     case WSAINVALIDPROVIDER:
1157       return "Invalid service provider version number";
1158 #endif
1159 #ifdef WSAPROVIDERFAILEDINIT
1160
1161     case WSAPROVIDERFAILEDINIT:
1162       return "Unable to initialize a service provider";
1163 #endif
1164
1165     case WSASYSCALLFAILURE:
1166       return "System call failure";
1167     }
1168   msg = strerror (error_number);
1169   if (msg == NULL)
1170     msg = "unknown";
1171
1172   return msg;
1173 #endif //DBUS_WINCE
1174 }
1175
1176
1177
1178 /* lan manager error codes */
1179 const char*
1180 _dbus_lm_strerror(int error_number)
1181 {
1182 #ifdef DBUS_WINCE
1183   // TODO
1184   return "unknown";
1185 #else
1186   const char *msg;
1187   switch (error_number)
1188     {
1189     case NERR_NetNotStarted:
1190       return "The workstation driver is not installed.";
1191     case NERR_UnknownServer:
1192       return "The server could not be located.";
1193     case NERR_ShareMem:
1194       return "An internal error occurred. The network cannot access a shared memory segment.";
1195     case NERR_NoNetworkResource:
1196       return "A network resource shortage occurred.";
1197     case NERR_RemoteOnly:
1198       return "This operation is not supported on workstations.";
1199     case NERR_DevNotRedirected:
1200       return "The device is not connected.";
1201     case NERR_ServerNotStarted:
1202       return "The Server service is not started.";
1203     case NERR_ItemNotFound:
1204       return "The queue is empty.";
1205     case NERR_UnknownDevDir:
1206       return "The device or directory does not exist.";
1207     case NERR_RedirectedPath:
1208       return "The operation is invalid on a redirected resource.";
1209     case NERR_DuplicateShare:
1210       return "The name has already been shared.";
1211     case NERR_NoRoom:
1212       return "The server is currently out of the requested resource.";
1213     case NERR_TooManyItems:
1214       return "Requested addition of items exceeds the maximum allowed.";
1215     case NERR_InvalidMaxUsers:
1216       return "The Peer service supports only two simultaneous users.";
1217     case NERR_BufTooSmall:
1218       return "The API return buffer is too small.";
1219     case NERR_RemoteErr:
1220       return "A remote API error occurred.";
1221     case NERR_LanmanIniError:
1222       return "An error occurred when opening or reading the configuration file.";
1223     case NERR_NetworkError:
1224       return "A general network error occurred.";
1225     case NERR_WkstaInconsistentState:
1226       return "The Workstation service is in an inconsistent state. Restart the computer before restarting the Workstation service.";
1227     case NERR_WkstaNotStarted:
1228       return "The Workstation service has not been started.";
1229     case NERR_BrowserNotStarted:
1230       return "The requested information is not available.";
1231     case NERR_InternalError:
1232       return "An internal error occurred.";
1233     case NERR_BadTransactConfig:
1234       return "The server is not configured for transactions.";
1235     case NERR_InvalidAPI:
1236       return "The requested API is not supported on the remote server.";
1237     case NERR_BadEventName:
1238       return "The event name is invalid.";
1239     case NERR_DupNameReboot:
1240       return "The computer name already exists on the network. Change it and restart the computer.";
1241     case NERR_CfgCompNotFound:
1242       return "The specified component could not be found in the configuration information.";
1243     case NERR_CfgParamNotFound:
1244       return "The specified parameter could not be found in the configuration information.";
1245     case NERR_LineTooLong:
1246       return "A line in the configuration file is too long.";
1247     case NERR_QNotFound:
1248       return "The printer does not exist.";
1249     case NERR_JobNotFound:
1250       return "The print job does not exist.";
1251     case NERR_DestNotFound:
1252       return "The printer destination cannot be found.";
1253     case NERR_DestExists:
1254       return "The printer destination already exists.";
1255     case NERR_QExists:
1256       return "The printer queue already exists.";
1257     case NERR_QNoRoom:
1258       return "No more printers can be added.";
1259     case NERR_JobNoRoom:
1260       return "No more print jobs can be added.";
1261     case NERR_DestNoRoom:
1262       return "No more printer destinations can be added.";
1263     case NERR_DestIdle:
1264       return "This printer destination is idle and cannot accept control operations.";
1265     case NERR_DestInvalidOp:
1266       return "This printer destination request contains an invalid control function.";
1267     case NERR_ProcNoRespond:
1268       return "The print processor is not responding.";
1269     case NERR_SpoolerNotLoaded:
1270       return "The spooler is not running.";
1271     case NERR_DestInvalidState:
1272       return "This operation cannot be performed on the print destination in its current state.";
1273     case NERR_QInvalidState:
1274       return "This operation cannot be performed on the printer queue in its current state.";
1275     case NERR_JobInvalidState:
1276       return "This operation cannot be performed on the print job in its current state.";
1277     case NERR_SpoolNoMemory:
1278       return "A spooler memory allocation failure occurred.";
1279     case NERR_DriverNotFound:
1280       return "The device driver does not exist.";
1281     case NERR_DataTypeInvalid:
1282       return "The data type is not supported by the print processor.";
1283     case NERR_ProcNotFound:
1284       return "The print processor is not installed.";
1285     case NERR_ServiceTableLocked:
1286       return "The service database is locked.";
1287     case NERR_ServiceTableFull:
1288       return "The service table is full.";
1289     case NERR_ServiceInstalled:
1290       return "The requested service has already been started.";
1291     case NERR_ServiceEntryLocked:
1292       return "The service does not respond to control actions.";
1293     case NERR_ServiceNotInstalled:
1294       return "The service has not been started.";
1295     case NERR_BadServiceName:
1296       return "The service name is invalid.";
1297     case NERR_ServiceCtlTimeout:
1298       return "The service is not responding to the control function.";
1299     case NERR_ServiceCtlBusy:
1300       return "The service control is busy.";
1301     case NERR_BadServiceProgName:
1302       return "The configuration file contains an invalid service program name.";
1303     case NERR_ServiceNotCtrl:
1304       return "The service could not be controlled in its present state.";
1305     case NERR_ServiceKillProc:
1306       return "The service ended abnormally.";
1307     case NERR_ServiceCtlNotValid:
1308       return "The requested pause or stop is not valid for this service.";
1309     case NERR_NotInDispatchTbl:
1310       return "The service control dispatcher could not find the service name in the dispatch table.";
1311     case NERR_BadControlRecv:
1312       return "The service control dispatcher pipe read failed.";
1313     case NERR_ServiceNotStarting:
1314       return "A thread for the new service could not be created.";
1315     case NERR_AlreadyLoggedOn:
1316       return "This workstation is already logged on to the local-area network.";
1317     case NERR_NotLoggedOn:
1318       return "The workstation is not logged on to the local-area network.";
1319     case NERR_BadUsername:
1320       return "The user name or group name parameter is invalid.";
1321     case NERR_BadPassword:
1322       return "The password parameter is invalid.";
1323     case NERR_UnableToAddName_W:
1324       return "@W The logon processor did not add the message alias.";
1325     case NERR_UnableToAddName_F:
1326       return "The logon processor did not add the message alias.";
1327     case NERR_UnableToDelName_W:
1328       return "@W The logoff processor did not delete the message alias.";
1329     case NERR_UnableToDelName_F:
1330       return "The logoff processor did not delete the message alias.";
1331     case NERR_LogonsPaused:
1332       return "Network logons are paused.";
1333     case NERR_LogonServerConflict:
1334       return "A centralized logon-server conflict occurred.";
1335     case NERR_LogonNoUserPath:
1336       return "The server is configured without a valid user path.";
1337     case NERR_LogonScriptError:
1338       return "An error occurred while loading or running the logon script.";
1339     case NERR_StandaloneLogon:
1340       return "The logon server was not specified. Your computer will be logged on as STANDALONE.";
1341     case NERR_LogonServerNotFound:
1342       return "The logon server could not be found.";
1343     case NERR_LogonDomainExists:
1344       return "There is already a logon domain for this computer.";
1345     case NERR_NonValidatedLogon:
1346       return "The logon server could not validate the logon.";
1347     case NERR_ACFNotFound:
1348       return "The security database could not be found.";
1349     case NERR_GroupNotFound:
1350       return "The group name could not be found.";
1351     case NERR_UserNotFound:
1352       return "The user name could not be found.";
1353     case NERR_ResourceNotFound:
1354       return "The resource name could not be found.";
1355     case NERR_GroupExists:
1356       return "The group already exists.";
1357     case NERR_UserExists:
1358       return "The user account already exists.";
1359     case NERR_ResourceExists:
1360       return "The resource permission list already exists.";
1361     case NERR_NotPrimary:
1362       return "This operation is only allowed on the primary domain controller of the domain.";
1363     case NERR_ACFNotLoaded:
1364       return "The security database has not been started.";
1365     case NERR_ACFNoRoom:
1366       return "There are too many names in the user accounts database.";
1367     case NERR_ACFFileIOFail:
1368       return "A disk I/O failure occurred.";
1369     case NERR_ACFTooManyLists:
1370       return "The limit of 64 entries per resource was exceeded.";
1371     case NERR_UserLogon:
1372       return "Deleting a user with a session is not allowed.";
1373     case NERR_ACFNoParent:
1374       return "The parent directory could not be located.";
1375     case NERR_CanNotGrowSegment:
1376       return "Unable to add to the security database session cache segment.";
1377     case NERR_SpeGroupOp:
1378       return "This operation is not allowed on this special group.";
1379     case NERR_NotInCache:
1380       return "This user is not cached in user accounts database session cache.";
1381     case NERR_UserInGroup:
1382       return "The user already belongs to this group.";
1383     case NERR_UserNotInGroup:
1384       return "The user does not belong to this group.";
1385     case NERR_AccountUndefined:
1386       return "This user account is undefined.";
1387     case NERR_AccountExpired:
1388       return "This user account has expired.";
1389     case NERR_InvalidWorkstation:
1390       return "The user is not allowed to log on from this workstation.";
1391     case NERR_InvalidLogonHours:
1392       return "The user is not allowed to log on at this time.";
1393     case NERR_PasswordExpired:
1394       return "The password of this user has expired.";
1395     case NERR_PasswordCantChange:
1396       return "The password of this user cannot change.";
1397     case NERR_PasswordHistConflict:
1398       return "This password cannot be used now.";
1399     case NERR_PasswordTooShort:
1400       return "The password does not meet the password policy requirements. Check the minimum password length, password complexity and password history requirements.";
1401     case NERR_PasswordTooRecent:
1402       return "The password of this user is too recent to change.";
1403     case NERR_InvalidDatabase:
1404       return "The security database is corrupted.";
1405     case NERR_DatabaseUpToDate:
1406       return "No updates are necessary to this replicant network/local security database.";
1407     case NERR_SyncRequired:
1408       return "This replicant database is outdated; synchronization is required.";
1409     case NERR_UseNotFound:
1410       return "The network connection could not be found.";
1411     case NERR_BadAsgType:
1412       return "This asg_type is invalid.";
1413     case NERR_DeviceIsShared:
1414       return "This device is currently being shared.";
1415     case NERR_NoComputerName:
1416       return "The computer name could not be added as a message alias. The name may already exist on the network.";
1417     case NERR_MsgAlreadyStarted:
1418       return "The Messenger service is already started.";
1419     case NERR_MsgInitFailed:
1420       return "The Messenger service failed to start.";
1421     case NERR_NameNotFound:
1422       return "The message alias could not be found on the network.";
1423     case NERR_AlreadyForwarded:
1424       return "This message alias has already been forwarded.";
1425     case NERR_AddForwarded:
1426       return "This message alias has been added but is still forwarded.";
1427     case NERR_AlreadyExists:
1428       return "This message alias already exists locally.";
1429     case NERR_TooManyNames:
1430       return "The maximum number of added message aliases has been exceeded.";
1431     case NERR_DelComputerName:
1432       return "The computer name could not be deleted.";
1433     case NERR_LocalForward:
1434       return "Messages cannot be forwarded back to the same workstation.";
1435     case NERR_GrpMsgProcessor:
1436       return "An error occurred in the domain message processor.";
1437     case NERR_PausedRemote:
1438       return "The message was sent, but the recipient has paused the Messenger service.";
1439     case NERR_BadReceive:
1440       return "The message was sent but not received.";
1441     case NERR_NameInUse:
1442       return "The message alias is currently in use. Try again later.";
1443     case NERR_MsgNotStarted:
1444       return "The Messenger service has not been started.";
1445     case NERR_NotLocalName:
1446       return "The name is not on the local computer.";
1447     case NERR_NoForwardName:
1448       return "The forwarded message alias could not be found on the network.";
1449     case NERR_RemoteFull:
1450       return "The message alias table on the remote station is full.";
1451     case NERR_NameNotForwarded:
1452       return "Messages for this alias are not currently being forwarded.";
1453     case NERR_TruncatedBroadcast:
1454       return "The broadcast message was truncated.";
1455     case NERR_InvalidDevice:
1456       return "This is an invalid device name.";
1457     case NERR_WriteFault:
1458       return "A write fault occurred.";
1459     case NERR_DuplicateName:
1460       return "A duplicate message alias exists on the network.";
1461     case NERR_DeleteLater:
1462       return "@W This message alias will be deleted later.";
1463     case NERR_IncompleteDel:
1464       return "The message alias was not successfully deleted from all networks.";
1465     case NERR_MultipleNets:
1466       return "This operation is not supported on computers with multiple networks.";
1467     case NERR_NetNameNotFound:
1468       return "This shared resource does not exist.";
1469     case NERR_DeviceNotShared:
1470       return "This device is not shared.";
1471     case NERR_ClientNameNotFound:
1472       return "A session does not exist with that computer name.";
1473     case NERR_FileIdNotFound:
1474       return "There is not an open file with that identification number.";
1475     case NERR_ExecFailure:
1476       return "A failure occurred when executing a remote administration command.";
1477     case NERR_TmpFile:
1478       return "A failure occurred when opening a remote temporary file.";
1479     case NERR_TooMuchData:
1480       return "The data returned from a remote administration command has been truncated to 64K.";
1481     case NERR_DeviceShareConflict:
1482       return "This device cannot be shared as both a spooled and a non-spooled resource.";
1483     case NERR_BrowserTableIncomplete:
1484       return "The information in the list of servers may be incorrect.";
1485     case NERR_NotLocalDomain:
1486       return "The computer is not active in this domain.";
1487 #ifdef NERR_IsDfsShare
1488
1489     case NERR_IsDfsShare:
1490       return "The share must be removed from the Distributed File System before it can be deleted.";
1491 #endif
1492
1493     case NERR_DevInvalidOpCode:
1494       return "The operation is invalid for this device.";
1495     case NERR_DevNotFound:
1496       return "This device cannot be shared.";
1497     case NERR_DevNotOpen:
1498       return "This device was not open.";
1499     case NERR_BadQueueDevString:
1500       return "This device name list is invalid.";
1501     case NERR_BadQueuePriority:
1502       return "The queue priority is invalid.";
1503     case NERR_NoCommDevs:
1504       return "There are no shared communication devices.";
1505     case NERR_QueueNotFound:
1506       return "The queue you specified does not exist.";
1507     case NERR_BadDevString:
1508       return "This list of devices is invalid.";
1509     case NERR_BadDev:
1510       return "The requested device is invalid.";
1511     case NERR_InUseBySpooler:
1512       return "This device is already in use by the spooler.";
1513     case NERR_CommDevInUse:
1514       return "This device is already in use as a communication device.";
1515     case NERR_InvalidComputer:
1516       return "This computer name is invalid.";
1517     case NERR_MaxLenExceeded:
1518       return "The string and prefix specified are too long.";
1519     case NERR_BadComponent:
1520       return "This path component is invalid.";
1521     case NERR_CantType:
1522       return "Could not determine the type of input.";
1523     case NERR_TooManyEntries:
1524       return "The buffer for types is not big enough.";
1525     case NERR_ProfileFileTooBig:
1526       return "Profile files cannot exceed 64K.";
1527     case NERR_ProfileOffset:
1528       return "The start offset is out of range.";
1529     case NERR_ProfileCleanup:
1530       return "The system cannot delete current connections to network resources.";
1531     case NERR_ProfileUnknownCmd:
1532       return "The system was unable to parse the command line in this file.";
1533     case NERR_ProfileLoadErr:
1534       return "An error occurred while loading the profile file.";
1535     case NERR_ProfileSaveErr:
1536       return "@W Errors occurred while saving the profile file. The profile was partially saved.";
1537     case NERR_LogOverflow:
1538       return "Log file %1 is full.";
1539     case NERR_LogFileChanged:
1540       return "This log file has changed between reads.";
1541     case NERR_LogFileCorrupt:
1542       return "Log file %1 is corrupt.";
1543     case NERR_SourceIsDir:
1544       return "The source path cannot be a directory.";
1545     case NERR_BadSource:
1546       return "The source path is illegal.";
1547     case NERR_BadDest:
1548       return "The destination path is illegal.";
1549     case NERR_DifferentServers:
1550       return "The source and destination paths are on different servers.";
1551     case NERR_RunSrvPaused:
1552       return "The Run server you requested is paused.";
1553     case NERR_ErrCommRunSrv:
1554       return "An error occurred when communicating with a Run server.";
1555     case NERR_ErrorExecingGhost:
1556       return "An error occurred when starting a background process.";
1557     case NERR_ShareNotFound:
1558       return "The shared resource you are connected to could not be found.";
1559     case NERR_InvalidLana:
1560       return "The LAN adapter number is invalid.";
1561     case NERR_OpenFiles:
1562       return "There are open files on the connection.";
1563     case NERR_ActiveConns:
1564       return "Active connections still exist.";
1565     case NERR_BadPasswordCore:
1566       return "This share name or password is invalid.";
1567     case NERR_DevInUse:
1568       return "The device is being accessed by an active process.";
1569     case NERR_LocalDrive:
1570       return "The drive letter is in use locally.";
1571     case NERR_AlertExists:
1572       return "The specified client is already registered for the specified event.";
1573     case NERR_TooManyAlerts:
1574       return "The alert table is full.";
1575     case NERR_NoSuchAlert:
1576       return "An invalid or nonexistent alert name was raised.";
1577     case NERR_BadRecipient:
1578       return "The alert recipient is invalid.";
1579     case NERR_AcctLimitExceeded:
1580       return "A user's session with this server has been deleted.";
1581     case NERR_InvalidLogSeek:
1582       return "The log file does not contain the requested record number.";
1583     case NERR_BadUasConfig:
1584       return "The user accounts database is not configured correctly.";
1585     case NERR_InvalidUASOp:
1586       return "This operation is not permitted when the Netlogon service is running.";
1587     case NERR_LastAdmin:
1588       return "This operation is not allowed on the last administrative account.";
1589     case NERR_DCNotFound:
1590       return "Could not find domain controller for this domain.";
1591     case NERR_LogonTrackingError:
1592       return "Could not set logon information for this user.";
1593     case NERR_NetlogonNotStarted:
1594       return "The Netlogon service has not been started.";
1595     case NERR_CanNotGrowUASFile:
1596       return "Unable to add to the user accounts database.";
1597     case NERR_TimeDiffAtDC:
1598       return "This server's clock is not synchronized with the primary domain controller's clock.";
1599     case NERR_PasswordMismatch:
1600       return "A password mismatch has been detected.";
1601     case NERR_NoSuchServer:
1602       return "The server identification does not specify a valid server.";
1603     case NERR_NoSuchSession:
1604       return "The session identification does not specify a valid session.";
1605     case NERR_NoSuchConnection:
1606       return "The connection identification does not specify a valid connection.";
1607     case NERR_TooManyServers:
1608       return "There is no space for another entry in the table of available servers.";
1609     case NERR_TooManySessions:
1610       return "The server has reached the maximum number of sessions it supports.";
1611     case NERR_TooManyConnections:
1612       return "The server has reached the maximum number of connections it supports.";
1613     case NERR_TooManyFiles:
1614       return "The server cannot open more files because it has reached its maximum number.";
1615     case NERR_NoAlternateServers:
1616       return "There are no alternate servers registered on this server.";
1617     case NERR_TryDownLevel:
1618       return "Try down-level (remote admin protocol) version of API instead.";
1619     case NERR_UPSDriverNotStarted:
1620       return "The UPS driver could not be accessed by the UPS service.";
1621     case NERR_UPSInvalidConfig:
1622       return "The UPS service is not configured correctly.";
1623     case NERR_UPSInvalidCommPort:
1624       return "The UPS service could not access the specified Comm Port.";
1625     case NERR_UPSSignalAsserted:
1626       return "The UPS indicated a line fail or low battery situation. Service not started.";
1627     case NERR_UPSShutdownFailed:
1628       return "The UPS service failed to perform a system shut down.";
1629     case NERR_BadDosRetCode:
1630       return "The program below returned an MS-DOS error code:";
1631     case NERR_ProgNeedsExtraMem:
1632       return "The program below needs more memory:";
1633     case NERR_BadDosFunction:
1634       return "The program below called an unsupported MS-DOS function:";
1635     case NERR_RemoteBootFailed:
1636       return "The workstation failed to boot.";
1637     case NERR_BadFileCheckSum:
1638       return "The file below is corrupt.";
1639     case NERR_NoRplBootSystem:
1640       return "No loader is specified in the boot-block definition file.";
1641     case NERR_RplLoadrNetBiosErr:
1642       return "NetBIOS returned an error:      The NCB and SMB are dumped above.";
1643     case NERR_RplLoadrDiskErr:
1644       return "A disk I/O error occurred.";
1645     case NERR_ImageParamErr:
1646       return "Image parameter substitution failed.";
1647     case NERR_TooManyImageParams:
1648       return "Too many image parameters cross disk sector boundaries.";
1649     case NERR_NonDosFloppyUsed:
1650       return "The image was not generated from an MS-DOS diskette formatted with /S.";
1651     case NERR_RplBootRestart:
1652       return "Remote boot will be restarted later.";
1653     case NERR_RplSrvrCallFailed:
1654       return "The call to the Remoteboot server failed.";
1655     case NERR_CantConnectRplSrvr:
1656       return "Cannot connect to the Remoteboot server.";
1657     case NERR_CantOpenImageFile:
1658       return "Cannot open image file on the Remoteboot server.";
1659     case NERR_CallingRplSrvr:
1660       return "Connecting to the Remoteboot server...";
1661     case NERR_StartingRplBoot:
1662       return "Connecting to the Remoteboot server...";
1663     case NERR_RplBootServiceTerm:
1664       return "Remote boot service was stopped; check the error log for the cause of the problem.";
1665     case NERR_RplBootStartFailed:
1666       return "Remote boot startup failed; check the error log for the cause of the problem.";
1667     case NERR_RPL_CONNECTED:
1668       return "A second connection to a Remoteboot resource is not allowed.";
1669     case NERR_BrowserConfiguredToNotRun:
1670       return "The browser service was configured with MaintainServerList=No.";
1671     case NERR_RplNoAdaptersStarted:
1672       return "Service failed to start since none of the network adapters started with this service.";
1673     case NERR_RplBadRegistry:
1674       return "Service failed to start due to bad startup information in the registry.";
1675     case NERR_RplBadDatabase:
1676       return "Service failed to start because its database is absent or corrupt.";
1677     case NERR_RplRplfilesShare:
1678       return "Service failed to start because RPLFILES share is absent.";
1679     case NERR_RplNotRplServer:
1680       return "Service failed to start because RPLUSER group is absent.";
1681     case NERR_RplCannotEnum:
1682       return "Cannot enumerate service records.";
1683     case NERR_RplWkstaInfoCorrupted:
1684       return "Workstation record information has been corrupted.";
1685     case NERR_RplWkstaNotFound:
1686       return "Workstation record was not found.";
1687     case NERR_RplWkstaNameUnavailable:
1688       return "Workstation name is in use by some other workstation.";
1689     case NERR_RplProfileInfoCorrupted:
1690       return "Profile record information has been corrupted.";
1691     case NERR_RplProfileNotFound:
1692       return "Profile record was not found.";
1693     case NERR_RplProfileNameUnavailable:
1694       return "Profile name is in use by some other profile.";
1695     case NERR_RplProfileNotEmpty:
1696       return "There are workstations using this profile.";
1697     case NERR_RplConfigInfoCorrupted:
1698       return "Configuration record information has been corrupted.";
1699     case NERR_RplConfigNotFound:
1700       return "Configuration record was not found.";
1701     case NERR_RplAdapterInfoCorrupted:
1702       return "Adapter ID record information has been corrupted.";
1703     case NERR_RplInternal:
1704       return "An internal service error has occurred.";
1705     case NERR_RplVendorInfoCorrupted:
1706       return "Vendor ID record information has been corrupted.";
1707     case NERR_RplBootInfoCorrupted:
1708       return "Boot block record information has been corrupted.";
1709     case NERR_RplWkstaNeedsUserAcct:
1710       return "The user account for this workstation record is missing.";
1711     case NERR_RplNeedsRPLUSERAcct:
1712       return "The RPLUSER local group could not be found.";
1713     case NERR_RplBootNotFound:
1714       return "Boot block record was not found.";
1715     case NERR_RplIncompatibleProfile:
1716       return "Chosen profile is incompatible with this workstation.";
1717     case NERR_RplAdapterNameUnavailable:
1718       return "Chosen network adapter ID is in use by some other workstation.";
1719     case NERR_RplConfigNotEmpty:
1720       return "There are profiles using this configuration.";
1721     case NERR_RplBootInUse:
1722       return "There are workstations, profiles, or configurations using this boot block.";
1723     case NERR_RplBackupDatabase:
1724       return "Service failed to backup Remoteboot database.";
1725     case NERR_RplAdapterNotFound:
1726       return "Adapter record was not found.";
1727     case NERR_RplVendorNotFound:
1728       return "Vendor record was not found.";
1729     case NERR_RplVendorNameUnavailable:
1730       return "Vendor name is in use by some other vendor record.";
1731     case NERR_RplBootNameUnavailable:
1732       return "(boot name, vendor ID) is in use by some other boot block record.";
1733     case NERR_RplConfigNameUnavailable:
1734       return "Configuration name is in use by some other configuration.";
1735     case NERR_DfsInternalCorruption:
1736       return "The internal database maintained by the Dfs service is corrupt.";
1737     case NERR_DfsVolumeDataCorrupt:
1738       return "One of the records in the internal Dfs database is corrupt.";
1739     case NERR_DfsNoSuchVolume:
1740       return "There is no DFS name whose entry path matches the input Entry Path.";
1741     case NERR_DfsVolumeAlreadyExists:
1742       return "A root or link with the given name already exists.";
1743     case NERR_DfsAlreadyShared:
1744       return "The server share specified is already shared in the Dfs.";
1745     case NERR_DfsNoSuchShare:
1746       return "The indicated server share does not support the indicated DFS namespace.";
1747     case NERR_DfsNotALeafVolume:
1748       return "The operation is not valid on this portion of the namespace.";
1749     case NERR_DfsLeafVolume:
1750       return "The operation is not valid on this portion of the namespace.";
1751     case NERR_DfsVolumeHasMultipleServers:
1752       return "The operation is ambiguous because the link has multiple servers.";
1753     case NERR_DfsCantCreateJunctionPoint:
1754       return "Unable to create a link.";
1755     case NERR_DfsServerNotDfsAware:
1756       return "The server is not Dfs Aware.";
1757     case NERR_DfsBadRenamePath:
1758       return "The specified rename target path is invalid.";
1759     case NERR_DfsVolumeIsOffline:
1760       return "The specified DFS link is offline.";
1761     case NERR_DfsNoSuchServer:
1762       return "The specified server is not a server for this link.";
1763     case NERR_DfsCyclicalName:
1764       return "A cycle in the Dfs name was detected.";
1765     case NERR_DfsNotSupportedInServerDfs:
1766       return "The operation is not supported on a server-based Dfs.";
1767     case NERR_DfsDuplicateService:
1768       return "This link is already supported by the specified server-share.";
1769     case NERR_DfsCantRemoveLastServerShare:
1770       return "Can't remove the last server-share supporting this root or link.";
1771     case NERR_DfsVolumeIsInterDfs:
1772       return "The operation is not supported for an Inter-DFS link.";
1773     case NERR_DfsInconsistent:
1774       return "The internal state of the Dfs Service has become inconsistent.";
1775     case NERR_DfsServerUpgraded:
1776       return "The Dfs Service has been installed on the specified server.";
1777     case NERR_DfsDataIsIdentical:
1778       return "The Dfs data being reconciled is identical.";
1779     case NERR_DfsCantRemoveDfsRoot:
1780       return "The DFS root cannot be deleted. Uninstall DFS if required.";
1781     case NERR_DfsChildOrParentInDfs:
1782       return "A child or parent directory of the share is already in a Dfs.";
1783     case NERR_DfsInternalError:
1784       return "Dfs internal error.";
1785       /* the following are not defined in mingw */
1786 #if 0
1787
1788     case NERR_SetupAlreadyJoined:
1789       return "This machine is already joined to a domain.";
1790     case NERR_SetupNotJoined:
1791       return "This machine is not currently joined to a domain.";
1792     case NERR_SetupDomainController:
1793       return "This machine is a domain controller and cannot be unjoined from a domain.";
1794     case NERR_DefaultJoinRequired:
1795       return "The destination domain controller does not support creating machine accounts in OUs.";
1796     case NERR_InvalidWorkgroupName:
1797       return "The specified workgroup name is invalid.";
1798     case NERR_NameUsesIncompatibleCodePage:
1799       return "The specified computer name is incompatible with the default language used on the domain controller.";
1800     case NERR_ComputerAccountNotFound:
1801       return "The specified computer account could not be found.";
1802     case NERR_PersonalSku:
1803       return "This version of Windows cannot be joined to a domain.";
1804     case NERR_PasswordMustChange:
1805       return "The password must change at the next logon.";
1806     case NERR_AccountLockedOut:
1807       return "The account is locked out.";
1808     case NERR_PasswordTooLong:
1809       return "The password is too long.";
1810     case NERR_PasswordNotComplexEnough:
1811       return "The password does not meet the complexity policy.";
1812     case NERR_PasswordFilterError:
1813       return "The password does not meet the requirements of the password filter DLLs.";
1814 #endif
1815
1816     }
1817   msg = strerror (error_number);
1818   if (msg == NULL)
1819     msg = "unknown";
1820
1821   return msg;
1822 #endif //DBUS_WINCE
1823 }
1824
1825 /**
1826  * Get a printable string describing the command used to execute
1827  * the process with pid.  This string should only be used for
1828  * informative purposes such as logging; it may not be trusted.
1829  *
1830  * The command is guaranteed to be printable ASCII and no longer
1831  * than max_len.
1832  *
1833  * @param pid Process id
1834  * @param str Append command to this string
1835  * @param max_len Maximum length of returned command
1836  * @param error return location for errors
1837  * @returns #FALSE on error
1838  */
1839 dbus_bool_t
1840 _dbus_command_for_pid (unsigned long  pid,
1841                        DBusString    *str,
1842                        int            max_len,
1843                        DBusError     *error)
1844 {
1845   // FIXME
1846   return FALSE;
1847 }