Add netdomjoin-gui (my first gui application), another libnetapi user.
authorGünther Deschner <gd@samba.org>
Fri, 21 Dec 2007 15:36:06 +0000 (16:36 +0100)
committerGünther Deschner <gd@samba.org>
Fri, 21 Dec 2007 15:36:06 +0000 (16:36 +0100)
Guenther
(This used to be commit cf57ade5ec4a808eccb19a7723d753742fb71ca9)

source3/lib/netapi/examples/Makefile.in
source3/lib/netapi/examples/logo.png [new file with mode: 0644]
source3/lib/netapi/examples/netdomjoin-gui.c [new file with mode: 0644]
source3/lib/netapi/examples/samba.ico [new file with mode: 0755]

index d618599433b25c67405620edf82ec6a6cee9a64c..119e722aec501b6a0d698e77f83cdd5286acb261 100644 (file)
@@ -1,8 +1,11 @@
+GTK_FLAGS=`pkg-config gtk+-2.0 --cflags`
+GTK_LIBS=`pkg-config gtk+-2.0 --libs`
+
 KRB5LIBS=@KRB5_LIBS@
 LDAP_LIBS=@LDAP_LIBS@
 LIBS=@LIBS@ -lnetapi
 DEVELOPER_CFLAGS=@DEVELOPER_CFLAGS@
-FLAGS=@CFLAGS@
+FLAGS=@CFLAGS@ $(GTK_FLAGS)
 CC=@CC@
 LDFLAGS=@PIE_LDFLAGS@ @LDFLAGS@
 DYNEXP=@DYNEXP@
@@ -22,8 +25,9 @@ COMPILE = $(COMPILE_CC)
 
 GETDC_OBJ = getdc.o
 NETDOMJOIN_OBJ = netdomjoin.o
+NETDOMJOIN_GUI_OBJ = netdomjoin-gui.o
 
-PROGS = getdc netdomjoin
+PROGS = getdc netdomjoin netdomjoin-gui
 
 all: $(PROGS)
 
@@ -35,5 +39,9 @@ netdomjoin: $(NETDOMJOIN_OBJ)
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(NETDOMJOIN_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
 
+netdomjoin-gui: $(NETDOMJOIN_GUI_OBJ)
+       @echo Linking $@
+       @$(CC) $(FLAGS) $(GTK_FLAGS) -o $@ $(NETDOMJOIN_GUI_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(GTK_LIBS)
+
 clean:
        @rm -f $(PROGS)
diff --git a/source3/lib/netapi/examples/logo.png b/source3/lib/netapi/examples/logo.png
new file mode 100644 (file)
index 0000000..6df4ace
Binary files /dev/null and b/source3/lib/netapi/examples/logo.png differ
diff --git a/source3/lib/netapi/examples/netdomjoin-gui.c b/source3/lib/netapi/examples/netdomjoin-gui.c
new file mode 100644 (file)
index 0000000..8ca6897
--- /dev/null
@@ -0,0 +1,1347 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  Join Support (gtk + netapi)
+ *  Copyright (C) Guenther Deschner 2007
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gprintf.h>
+
+#include <libnetapi.h>
+
+#define MAX_CRED_LEN 256
+#define MAX_NETBIOS_NAME_LEN 15
+
+#define SAMBA_ICON_PATH  "/usr/share/pixmaps/samba/samba.ico"
+#define SAMBA_IMAGE_PATH "/usr/share/pixmaps/samba/logo.png"
+
+#define WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
+#define WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ( 0x00000004 )
+#define WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE ( 0x00000002 )
+#define WKSSVC_JOIN_FLAGS_JOIN_TYPE ( 0x00000001 )
+
+#define NetSetupWorkgroupName ( 2 )
+#define NetSetupDomainName ( 3 )
+
+#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
+
+struct srvsvc_NetSrvInfo1005 {
+       const char *comment;/* [unique,charset(UTF16)] */
+};
+
+static gboolean verbose = FALSE;
+
+typedef struct join_state {
+       struct libnetapi_ctx *ctx;
+       GtkWidget *window_main;
+       GtkWidget *window_parent;
+       GtkWidget *window_do_change;
+       GtkWidget *window_creds_prompt;
+       GtkWidget *entry_account;
+       GtkWidget *entry_password;
+       GtkWidget *entry_domain;
+       GtkWidget *entry_workgroup;
+       GtkWidget *button_ok;
+       GtkWidget *button_apply;
+       GtkWidget *button_ok_creds;
+       GtkWidget *label_reboot;
+       GtkWidget *label_current_name_buffer;
+       GtkWidget *label_current_name_type;
+       GtkWidget *label_full_computer_name;
+       uint16_t name_type_initial;
+       uint16_t name_type_new;
+       char *name_buffer_initial;
+       char *name_buffer_new;
+       char *password;
+       char *account;
+       char *comment;
+       char *comment_new;
+       char *my_fqdn;
+       char *my_dnsdomain;
+       char *my_hostname;
+       uint16_t server_role;
+       gboolean settings_changed;
+       gboolean hostname_changed;
+} join_state;
+
+static void debug(const char *format, ...)
+{
+       va_list args;
+
+       if (!verbose) {
+               return;
+       }
+
+       va_start(args, format);
+       g_vprintf(format, args);
+       va_end(args);
+}
+
+static gboolean callback_delete_event(GtkWidget *widget,
+                                     GdkEvent *event,
+                                     gpointer data)
+{
+       gtk_main_quit();
+       return FALSE;
+}
+
+static void callback_do_close(GtkWidget *widget,
+                             gpointer data)
+{
+       debug("Closing now...\n");
+       gtk_widget_destroy(data);
+}
+
+static void free_join_state(struct join_state *s)
+{
+       SAFE_FREE(s->name_buffer_initial);
+       SAFE_FREE(s->name_buffer_new);
+       SAFE_FREE(s->password);
+       SAFE_FREE(s->account);
+       SAFE_FREE(s->comment);
+       SAFE_FREE(s->comment_new);
+       SAFE_FREE(s->my_fqdn);
+       SAFE_FREE(s->my_dnsdomain);
+       SAFE_FREE(s->my_hostname);
+
+}
+
+static void do_cleanup(struct join_state *state)
+{
+       libnetapi_free(state->ctx);
+       free_join_state(state);
+}
+
+static void callback_apply_description_change(GtkWidget *widget,
+                                             gpointer data)
+{
+       struct join_state *state = (struct join_state *)data;
+       NET_API_STATUS status = 0;
+       uint32_t parm_err = 0;
+       struct srvsvc_NetSrvInfo1005 info1005;
+       GtkWidget *dialog;
+
+       info1005.comment = state->comment_new;
+
+       status = NetServerSetInfo(NULL, 1005, (uint8_t *)&info1005, &parm_err); 
+       if (status) {
+               debug("NetServerSetInfo failed with: %s\n",
+                       libnetapi_errstr(state->ctx, status));
+               dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
+                                               GTK_DIALOG_DESTROY_WITH_PARENT,
+                                               GTK_MESSAGE_ERROR,
+                                               GTK_BUTTONS_OK,
+                                               "Failed to change computer description: %s.",
+                                               libnetapi_errstr(state->ctx, status));
+               g_signal_connect_swapped(dialog, "response",
+                                        G_CALLBACK(gtk_widget_destroy),
+                                        dialog);
+
+               gtk_widget_show(dialog);
+               return;
+       }
+
+       gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
+}
+
+static void callback_do_exit(GtkWidget *widget,
+                            gpointer data)
+{
+       GtkWidget *dialog;
+       gint result;
+       struct join_state *state = (struct join_state *)data;
+
+       if (!state->settings_changed) {
+               callback_delete_event(NULL, NULL, NULL);
+               return;
+       }
+
+       dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
+                                       GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       GTK_MESSAGE_QUESTION,
+                                       GTK_BUTTONS_YES_NO,
+                                       "You must restart your computer before the new settings will take effect.");
+       result = gtk_dialog_run(GTK_DIALOG(dialog));
+       switch (result) {
+               case GTK_RESPONSE_YES:
+                       g_print("would reboot here\n");
+                       break;
+               case GTK_RESPONSE_NO:
+               default:
+                       break;
+       }
+       gtk_widget_destroy(dialog);
+       gtk_widget_destroy(state->window_main);
+       do_cleanup(state);
+       exit(0);
+}
+
+
+static void callback_do_reboot(GtkWidget *widget,
+                              gpointer data,
+                              gpointer data2)
+{
+       GtkWidget *dialog;
+       struct join_state *state = (struct join_state *)data2;
+
+       debug("callback_do_reboot\n");
+
+       state->settings_changed = TRUE;
+       dialog = gtk_message_dialog_new(GTK_WINDOW(data),
+                                       GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       GTK_MESSAGE_INFO,
+                                       GTK_BUTTONS_OK,
+                                       "You must restart this computer for the changes to take effect.");
+#if 0
+       g_signal_connect_swapped(dialog, "response",
+                                G_CALLBACK(gtk_widget_destroy),
+                                dialog);
+
+       debug("showing dialog\n");
+       gtk_widget_show(dialog);
+#else
+       gtk_dialog_run(GTK_DIALOG(dialog));
+       gtk_widget_destroy(dialog);
+#endif
+
+       gtk_label_set_text(GTK_LABEL(state->label_reboot), "Changes will take effect after you restart this computer");
+
+       debug("destroying do_change window\n");
+       gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
+
+       {
+               uint32_t status;
+               const char *buffer;
+               uint16_t type;
+
+               status = NetGetJoinInformation(NULL, &buffer, &type);
+               if (status != 0) {
+                       g_print("failed to query status\n");
+                       return;
+               }
+
+               debug("got new status: %s\n", buffer);
+#if 0
+               SAFE_FREE(state->name_buffer_new);
+               state->name_buffer_new = strdup(buffer);
+               SAFE_FREE(buffer);
+               state->name_type_new = type;
+#endif
+               gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer), state->name_buffer_new);
+               if (state->name_type_new == 3) {
+                       gtk_label_set_text(GTK_LABEL(state->label_current_name_type), "Domain:");
+               } else {
+                       gtk_label_set_text(GTK_LABEL(state->label_current_name_type), "Workgroup:");
+               }
+       }
+}
+
+static void callback_return_username(GtkWidget *widget,
+                                    gpointer data)
+{
+       const gchar *entry_text;
+       struct join_state *state = (struct join_state *)data;
+       if (!widget) {
+               return;
+       }
+       entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+       debug("callback_return_username: %s\n", entry_text);
+       SAFE_FREE(state->account);
+       state->account = strdup(entry_text);
+}
+
+static void callback_return_username_and_enter(GtkWidget *widget,
+                                              gpointer data)
+{
+       const gchar *entry_text;
+       struct join_state *state = (struct join_state *)data;
+       if (!widget) {
+               return;
+       }
+       entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+       debug("callback_return_username: %s\n", entry_text);
+       SAFE_FREE(state->account);
+       state->account = strdup(entry_text);
+       g_signal_emit_by_name(state->button_ok_creds, "clicked");
+}
+
+static void callback_return_password(GtkWidget *widget,
+                                    gpointer data)
+{
+       const gchar *entry_text;
+       struct join_state *state = (struct join_state *)data;
+       if (!widget) {
+               return;
+       }
+       entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+#ifdef DEBUG_PASSWORD
+       debug("callback_return_password: %s\n", entry_text);
+#else
+       debug("callback_return_password: (not printed)\n");
+#endif
+       SAFE_FREE(state->password);
+       state->password = strdup(entry_text);
+}
+
+static void callback_return_password_and_enter(GtkWidget *widget,
+                                              gpointer data)
+{
+       const gchar *entry_text;
+       struct join_state *state = (struct join_state *)data;
+       if (!widget) {
+               return;
+       }
+       entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+#ifdef DEBUG_PASSWORD
+       debug("callback_return_password: %s\n", entry_text);
+#else
+       debug("callback_return_password: (not printed)\n");
+#endif
+       SAFE_FREE(state->password);
+       state->password = strdup(entry_text);
+       g_signal_emit_by_name(state->button_ok_creds, "clicked");
+}
+
+static void callback_do_hostname_change(GtkWidget *widget,
+                                       gpointer data)
+{
+       GtkWidget *dialog;
+       const char *str = NULL;
+
+       struct join_state *state = (struct join_state *)data;
+
+       switch (state->name_type_initial) {
+               case NetSetupDomainName:
+                       str = "To be implemented: call NetRenameMachineInDomain\n";
+                       break;
+               case NetSetupWorkgroupName:
+                       str = "To be implemented: call SetComputerNameEx\n";
+                       break;
+               default:
+                       break;
+       }
+
+       dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+                                       GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       GTK_MESSAGE_ERROR,
+                                       GTK_BUTTONS_CLOSE,
+                                       str);
+
+       g_signal_connect_swapped(dialog, "response",
+                                G_CALLBACK(gtk_widget_destroy),
+                                dialog);
+       gtk_widget_show(dialog);
+}
+
+static void callback_do_join(GtkWidget *widget,
+                            gpointer data)
+{
+       GtkWidget *dialog;
+
+       NET_API_STATUS status;
+       const char *err_str = NULL;
+       uint32_t join_flags = 0;
+       uint32_t unjoin_flags = 0;
+       gboolean domain_join = FALSE;
+       gboolean try_unjoin = FALSE;
+       const char *domain_or_workgroup = NULL;
+
+       struct join_state *state = (struct join_state *)data;
+
+       callback_return_username(state->entry_account, state);
+       callback_return_password(state->entry_password, state);
+
+       if (state->window_creds_prompt) {
+               gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
+       }
+
+       if (state->name_type_new == NetSetupDomainName) {
+               domain_join = TRUE;
+               join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
+                            WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
+                            WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED; /* for testing */
+               domain_or_workgroup = "domain";
+       } else {
+               domain_or_workgroup = "workgroup";
+       }
+
+       if ((state->name_type_initial == NetSetupDomainName) &&
+           (state->name_type_new == NetSetupWorkgroupName)) {
+               try_unjoin = TRUE;
+               unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
+                              WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
+       }
+
+       debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
+               domain_or_workgroup,
+               state->name_buffer_new,
+               join_flags);
+       if (domain_join) {
+               debug("as %s ", state->account);
+#ifdef DEBUG_PASSWORD
+               debug("with %s ", state->password);
+#endif
+       }
+       debug("\n");
+       if (try_unjoin) {
+
+               debug("callback_do_join: Unjoining\n");
+
+               status = NetUnjoinDomain(NULL,
+                                        state->account,
+                                        state->password,
+                                        unjoin_flags);
+               if (status != 0) {
+                       err_str = libnetapi_errstr(state->ctx, status);
+                       g_print("callback_do_join: failed to unjoin (%s)\n",
+                               err_str);
+
+                       dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+                                                       GTK_DIALOG_DESTROY_WITH_PARENT,
+                                                       GTK_MESSAGE_ERROR,
+                                                       GTK_BUTTONS_CLOSE,
+                                                       "The following error occured attempting to unjoin the %s: \"%s\": %s",
+                                                       domain_or_workgroup,
+                                                       state->name_buffer_new,
+                                                       err_str);
+
+                       g_signal_connect_swapped(dialog, "response",
+                                                G_CALLBACK(gtk_widget_destroy),
+                                                dialog);
+
+                       gtk_widget_show(dialog);
+
+                       return;
+               }
+
+       }
+       status = NetJoinDomain(NULL,
+                              state->name_buffer_new,
+                              NULL,
+                              state->account,
+                              state->password,
+                              join_flags);
+       if (status != 0) {
+               err_str = libnetapi_errstr(state->ctx, status);
+               g_print("callback_do_join: failed to join (%s)\n", err_str);
+
+               dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+                                               GTK_DIALOG_DESTROY_WITH_PARENT,
+                                               GTK_MESSAGE_ERROR,
+                                               GTK_BUTTONS_CLOSE,
+                                               "The following error occured attempting to join the %s: \"%s\": %s",
+                                               domain_or_workgroup,
+                                               state->name_buffer_new,
+                                               err_str);
+
+               g_signal_connect_swapped(dialog, "response",
+                                        G_CALLBACK(gtk_widget_destroy),
+                                        dialog);
+
+               gtk_widget_show(dialog);
+
+               return;
+       }
+
+       debug("callback_do_join: Successfully joined %s\n",
+               domain_or_workgroup);
+
+       dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
+                                       GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       GTK_MESSAGE_INFO,
+                                       GTK_BUTTONS_OK,
+                                       "Welcome to the %s %s.",
+                                       state->name_buffer_new,
+                                       domain_or_workgroup);
+
+       gtk_dialog_run(GTK_DIALOG(dialog));
+       gtk_widget_destroy(dialog);
+
+       callback_do_reboot(NULL, state->window_parent, state);
+}
+
+static void callback_creds_prompt(GtkWidget *widget,
+                                 gpointer data)
+{
+       GtkWidget *window;
+       GtkWidget *box1;
+       GtkWidget *bbox;
+       GtkWidget *button;
+       GtkWidget *label;
+
+       struct join_state *state = (struct join_state *)data;
+
+       debug("callback_creds_prompt:\n");
+
+       state->window_parent = state->window_do_change;
+
+       if (state->hostname_changed) {
+               return callback_do_hostname_change(NULL, state);
+       }
+
+       if ((state->name_type_initial != NetSetupDomainName) &&
+           (state->name_type_new != NetSetupDomainName)) {
+               return callback_do_join(NULL, state);
+       }
+
+       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+       gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
+       gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+       gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
+       gtk_widget_set_size_request(GTK_WIDGET(window), 380, 280);
+       gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+/*     gtk_window_set_icon_name(GTK_WIDGET(window), GTK_STOCK_DIALOG_AUTHENTICATION); */
+       state->window_creds_prompt = window;
+
+       g_signal_connect(G_OBJECT(window), "delete_event",
+                        G_CALLBACK(callback_do_close), window);
+
+       gtk_container_set_border_width(GTK_CONTAINER(window), 10);
+
+       box1 = gtk_vbox_new(FALSE, 0);
+
+       gtk_container_add(GTK_CONTAINER(window), box1);
+
+       if ((state->name_type_initial == NetSetupDomainName) &&
+           (state->name_type_new == NetSetupWorkgroupName)) {
+               label = gtk_label_new("Enter the name and password of an account with permission to leave the domain.\n");
+       } else {
+               label = gtk_label_new("Enter the name and password of an account with permission to join the domain.\n");
+       }
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+       gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+
+       gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
+
+       gtk_widget_show(label);
+
+       /* USER NAME */
+       label = gtk_label_new("User name:");
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+       gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
+       gtk_widget_show(label);
+
+       state->entry_account = gtk_entry_new();
+       gtk_entry_set_max_length(GTK_ENTRY(state->entry_account), MAX_CRED_LEN);
+       g_signal_connect(G_OBJECT(state->entry_account), "activate",
+                        G_CALLBACK(callback_return_username_and_enter),
+                        (gpointer)state);
+       gtk_editable_select_region(GTK_EDITABLE(state->entry_account),
+                                  0, GTK_ENTRY(state->entry_account)->text_length);
+       gtk_box_pack_start(GTK_BOX(box1), state->entry_account, TRUE, TRUE, 0);
+       gtk_widget_show(state->entry_account);
+
+       /* PASSWORD */
+       label = gtk_label_new("Password:");
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+       gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
+       gtk_widget_show(label);
+
+       state->entry_password = gtk_entry_new();
+       gtk_entry_set_max_length(GTK_ENTRY(state->entry_password), MAX_CRED_LEN);
+       gtk_entry_set_visibility(GTK_ENTRY(state->entry_password), FALSE);
+       g_signal_connect(G_OBJECT(state->entry_password), "activate",
+                        G_CALLBACK(callback_return_password_and_enter),
+                        (gpointer)state);
+       gtk_editable_set_editable(GTK_EDITABLE(state->entry_password), TRUE);
+       gtk_editable_select_region(GTK_EDITABLE(state->entry_password),
+                                  0, GTK_ENTRY(state->entry_password)->text_length);
+       gtk_box_pack_start(GTK_BOX(box1), state->entry_password, TRUE, TRUE, 0);
+       gtk_widget_show(state->entry_password);
+
+       bbox = gtk_hbutton_box_new();
+       gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
+       gtk_container_add(GTK_CONTAINER(box1), bbox);
+       gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+       gtk_box_set_spacing(GTK_BOX(bbox), 10);
+
+       state->button_ok_creds = gtk_button_new_from_stock(GTK_STOCK_OK);
+       gtk_widget_grab_focus(GTK_WIDGET(state->button_ok_creds));
+       gtk_container_add(GTK_CONTAINER(bbox), state->button_ok_creds);
+       g_signal_connect(G_OBJECT(state->button_ok_creds), "clicked",
+                        G_CALLBACK(callback_do_join),
+                        (gpointer)state);
+       gtk_widget_show(state->button_ok_creds);
+
+       button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+       gtk_container_add(GTK_CONTAINER(bbox), button);
+       g_signal_connect(G_OBJECT(button), "clicked",
+                        G_CALLBACK(callback_do_close), (gpointer) window);
+       gtk_widget_show_all(window);
+}
+
+static void callback_enter_hostname_and_unlock(GtkWidget *widget,
+                                              gpointer data)
+{
+       const gchar *entry_text = NULL;
+       char *str = NULL;
+       struct join_state *state = (struct join_state *)data;
+
+       entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+       debug("callback_enter_hostname_and_unlock: %s\n", entry_text);
+       if (!entry_text || entry_text[0] == 0) {
+               state->hostname_changed = FALSE;
+               gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+               return;
+       }
+       if (strcasecmp(state->my_hostname, entry_text) == 0) {
+               state->hostname_changed = FALSE;
+               gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+               return;
+       }
+       state->hostname_changed = TRUE;
+       if (state->name_type_initial == NetSetupDomainName) {
+               asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain);
+       } else {
+               asprintf(&str, "%s.", entry_text);
+       }
+       gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
+       free(str);
+
+       if (state->hostname_changed && str && str[0] != 0 && str[0] != '.') {
+               gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
+       }
+}
+
+static void callback_enter_computer_description_and_unlock(GtkWidget *widget,
+                                                          gpointer data)
+{
+       const gchar *entry_text = NULL;
+       struct join_state *state = (struct join_state *)data;
+       int string_unchanged = 0;
+
+       entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+       debug("callback_enter_computer_description_and_unlock: %s\n",
+               entry_text);
+#if 0
+       if (!entry_text || entry_text[0] == 0) {
+               string_unchanged = 1;
+               gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
+                                        FALSE);
+               return;
+       }
+#endif
+       if (entry_text && strcasecmp(state->comment, entry_text) == 0) {
+               string_unchanged = 1;
+               gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
+                                        FALSE);
+               return;
+       }
+
+       gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), TRUE);
+       SAFE_FREE(state->comment_new);
+       state->comment_new = strdup(entry_text);
+
+}
+
+
+static void callback_enter_workgroup_and_unlock(GtkWidget *widget,
+                                               gpointer data)
+{
+       const gchar *entry_text = NULL;
+       struct join_state *state = (struct join_state *)data;
+
+       entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+       debug("callback_enter_workgroup_and_unlock: %s\n", entry_text);
+       if (!entry_text || entry_text[0] == 0) {
+               gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+               return;
+       }
+       if (strcasecmp(state->name_buffer_initial, entry_text) == 0) {
+               gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+               return;
+       }
+       gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
+       SAFE_FREE(state->name_buffer_new);
+       state->name_buffer_new = strdup(entry_text);
+       state->name_type_new = NetSetupWorkgroupName;
+}
+
+static void callback_enter_domain_and_unlock(GtkWidget *widget,
+                                            gpointer data)
+{
+       const gchar *entry_text = NULL;
+       struct join_state *state = (struct join_state *)data;
+
+       entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
+       debug("callback_enter_domain_and_unlock: %s\n", entry_text);
+       if (!entry_text || entry_text[0] == 0) {
+               gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+               return;
+       }
+       if (strcasecmp(state->name_buffer_initial, entry_text) == 0) {
+               gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
+               return;
+       }
+       gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
+       SAFE_FREE(state->name_buffer_new);
+       state->name_buffer_new = strdup(entry_text);
+       state->name_type_new = NetSetupDomainName;
+}
+
+static void callback_continue(GtkWidget *widget,
+                             gpointer data)
+{
+       struct join_state *state = (struct join_state *)data;
+
+       gtk_widget_grab_focus(GTK_WIDGET(state->button_ok));
+       g_signal_emit_by_name(state->button_ok, "clicked");
+}
+
+static void callback_apply_continue(GtkWidget *widget,
+                                   gpointer data)
+{
+       struct join_state *state = (struct join_state *)data;
+
+       gtk_widget_grab_focus(GTK_WIDGET(state->button_apply));
+       g_signal_emit_by_name(state->button_apply, "clicked");
+}
+
+static void callback_do_join_workgroup(GtkWidget *widget,
+                                      gpointer data)
+{
+       struct join_state *state = (struct join_state *)data;
+       debug("callback_do_join_workgroup choosen\n");
+       gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
+       gtk_widget_grab_focus(GTK_WIDGET(state->entry_workgroup));
+       gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
+       callback_enter_workgroup_and_unlock(state->entry_workgroup, state); /* TEST */
+}
+
+static void callback_do_join_domain(GtkWidget *widget,
+                                   gpointer data)
+{
+       struct join_state *state = (struct join_state *)data;
+       debug("callback_do_join_domain choosen\n");
+       gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), TRUE);
+       gtk_widget_grab_focus(GTK_WIDGET(state->entry_domain));
+       gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), FALSE);
+       callback_enter_domain_and_unlock(state->entry_domain, state); /* TEST */
+}
+
+static void callback_do_change(GtkWidget *widget,
+                              gpointer data)
+{
+       GtkWidget *window;
+       GtkWidget *box1;
+       GtkWidget *bbox;
+       GtkWidget *button_workgroup;
+       GtkWidget *button_domain;
+       GtkWidget *button;
+       GtkWidget *label;
+       GtkWidget *frame_horz;
+       GtkWidget *vbox;
+       GtkWidget *entry;
+       GSList *group;
+
+       struct join_state *state = (struct join_state *)data;
+
+       debug("callback_do_change called\n");
+
+       if (state->server_role == 3) {
+               GtkWidget *dialog;
+               dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
+                                               GTK_DIALOG_DESTROY_WITH_PARENT,
+                                               GTK_MESSAGE_ERROR,
+                                               GTK_BUTTONS_OK,
+                                               "Domain controller cannot be moved from one domain to another, they must first be demoted. Renaming this domain controller may cause it to become temporarily unavailable to users and computers. For information on renaming domain controllers, including alternate renaming methods, see Help and Support. To continue renaming this domain controller, click OK.");
+               g_signal_connect_swapped(dialog, "response",
+                                        G_CALLBACK(gtk_widget_destroy),
+                                        dialog);
+
+               gtk_widget_show(dialog);
+               return;
+       }
+
+       state->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
+       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+       gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
+       gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+       gtk_widget_set_size_request(GTK_WIDGET(window), 480, 500); /* breite * höhe */
+       gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+
+       g_signal_connect(G_OBJECT(window), "delete_event",
+                        G_CALLBACK(callback_do_close), window);
+
+       gtk_container_set_border_width(GTK_CONTAINER(window), 10);
+
+       box1 = gtk_vbox_new(FALSE, 0);
+       gtk_container_add(GTK_CONTAINER(window), box1);
+
+       label = gtk_label_new("You can change the name and membership of this computer. Changes may affect access to network ressources.");
+       gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+       gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
+       gtk_widget_show(label);
+
+       /* COMPUTER NAME */
+       label = gtk_label_new("Computer name:");
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+       gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
+       gtk_widget_show(label);
+
+       state->label_full_computer_name = gtk_label_new(NULL);
+       {
+               entry = gtk_entry_new();
+               gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_NETBIOS_NAME_LEN);
+               g_signal_connect(G_OBJECT(entry), "changed",
+                                G_CALLBACK(callback_enter_hostname_and_unlock),
+                                (gpointer)state);
+               gtk_entry_set_text(GTK_ENTRY(entry), state->my_hostname);
+               gtk_editable_select_region(GTK_EDITABLE(entry),
+                                          0, GTK_ENTRY(entry)->text_length);
+
+               gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
+               gtk_box_pack_start(GTK_BOX(box1), entry, TRUE, TRUE, 0);
+               gtk_widget_show(entry);
+       }
+
+       /* FULL COMPUTER NAME */
+       label = gtk_label_new("Full computer name:");
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+       gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
+       gtk_widget_show(label);
+
+       {
+               const gchar *entry_text;
+               char *str = NULL;
+               entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
+               if (state->name_type_initial == NetSetupDomainName) {
+                       asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain);
+               } else {
+                       asprintf(&str, "%s.", entry_text);
+               }
+               gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
+               free(str);
+               gtk_misc_set_alignment(GTK_MISC(state->label_full_computer_name), 0, 0);
+               gtk_box_pack_start(GTK_BOX(box1), state->label_full_computer_name, TRUE, TRUE, 0);
+               gtk_widget_show(state->label_full_computer_name);
+       }
+
+       /* BOX */
+       frame_horz = gtk_frame_new ("Member Of");
+       gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
+
+       vbox = gtk_vbox_new(FALSE, 0);
+       gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
+       gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
+
+       /* TWO ENTRIES */
+       state->entry_workgroup = gtk_entry_new();
+       state->entry_domain = gtk_entry_new();
+
+       /* DOMAIN */
+       button_domain = gtk_radio_button_new_with_label(NULL, "Domain");
+       if (state->name_type_initial == NetSetupDomainName) {
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_domain), TRUE);
+       }
+       gtk_box_pack_start(GTK_BOX(vbox), button_domain, TRUE, TRUE, 0);
+       g_signal_connect(G_OBJECT(button_domain), "clicked",
+                        G_CALLBACK(callback_do_join_domain),
+                        (gpointer)state);
+
+       {
+               gtk_entry_set_max_length(GTK_ENTRY(state->entry_domain), 50);
+               g_signal_connect(G_OBJECT(state->entry_domain), "changed",
+                                G_CALLBACK(callback_enter_domain_and_unlock),
+                                (gpointer)state);
+               g_signal_connect(G_OBJECT(state->entry_domain), "activate",
+                                G_CALLBACK(callback_continue),
+                                (gpointer)state);
+               if (state->name_type_initial == NetSetupDomainName) {
+                       gtk_entry_set_text(GTK_ENTRY(state->entry_domain), state->name_buffer_initial);
+                       gtk_widget_set_sensitive(state->entry_workgroup, FALSE);
+                       gtk_widget_set_sensitive(state->entry_domain, TRUE);
+               }
+               gtk_editable_set_editable(GTK_EDITABLE(state->entry_domain), TRUE);
+               gtk_box_pack_start(GTK_BOX(vbox), state->entry_domain, TRUE, TRUE, 0);
+               gtk_widget_show(state->entry_domain);
+       }
+       gtk_widget_show(button_domain);
+
+       /* WORKGROUP */
+       group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button_domain));
+       button_workgroup = gtk_radio_button_new_with_label(group, "Workgroup");
+       if (state->name_type_initial == NetSetupWorkgroupName) {
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_workgroup), TRUE);
+       }
+       gtk_box_pack_start(GTK_BOX(vbox), button_workgroup, TRUE, TRUE, 0);
+       g_signal_connect(G_OBJECT(button_workgroup), "clicked",
+                        G_CALLBACK(callback_do_join_workgroup),
+                        (gpointer)state);
+       {
+               gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup), MAX_NETBIOS_NAME_LEN);
+               g_signal_connect(G_OBJECT(state->entry_workgroup), "changed",
+                                G_CALLBACK(callback_enter_workgroup_and_unlock),
+                                (gpointer)state);
+               g_signal_connect(G_OBJECT(state->entry_workgroup), "activate",
+                                G_CALLBACK(callback_continue),
+                                (gpointer)state);
+
+               if (state->name_type_initial == NetSetupWorkgroupName) {
+                       gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup), state->name_buffer_initial);
+                       gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
+                       gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
+               }
+               gtk_box_pack_start(GTK_BOX(vbox), state->entry_workgroup, TRUE, TRUE, 0);
+               gtk_widget_show(state->entry_workgroup);
+       }
+       gtk_widget_show(button_workgroup);
+
+       /* BUTTONS */
+       bbox = gtk_hbutton_box_new();
+       gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
+       gtk_container_add(GTK_CONTAINER(box1), bbox);
+       gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+       gtk_box_set_spacing(GTK_BOX(bbox), 10);
+
+       state->window_do_change = window;
+       gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE); /* !!! */
+       gtk_container_add(GTK_CONTAINER(bbox), state->button_ok);
+       g_signal_connect(G_OBJECT(state->button_ok), "clicked",
+                        G_CALLBACK(callback_creds_prompt),
+                        (gpointer)state);
+
+       button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+       gtk_container_add(GTK_CONTAINER(bbox), button);
+       g_signal_connect(G_OBJECT(button), "clicked",
+                        G_CALLBACK(callback_do_close),
+                        (gpointer)window);
+
+       gtk_widget_show_all(window);
+
+}
+
+static void callback_do_about(GtkWidget *widget,
+                            gpointer data)
+{
+       GdkPixbuf *logo;
+       GError    *error = NULL;
+
+       debug("callback_do_about called\n");
+
+       logo = gdk_pixbuf_new_from_file(SAMBA_IMAGE_PATH,
+                                       &error);
+       if (logo == NULL) {
+               g_print("failed to load logo from %s: %s\n",
+                       SAMBA_IMAGE_PATH, error->message);
+       }
+
+       gtk_show_about_dialog(data,
+                             "name", "Samba",
+                             "version", "3.2.0pre2-GIT-904a90-test",
+                             "copyright", "Copyright Andrew Tridgell and the Samba Team 1992-2007",
+                             "website", "http://www.samba.org",
+                             "license", "GPLv3",
+                             "logo", logo,
+                             "comments", "Samba gtk domain join utility",
+                             NULL);
+}
+
+static int draw_main_window(struct join_state *state)
+{
+       GtkWidget *window;
+       GtkWidget *button;
+       GtkWidget *label;
+       GtkWidget *main_vbox;
+       GtkWidget *vbox;
+       GtkWidget *hbox;
+       GtkWidget *bbox;
+       GtkWidget *image;
+       GtkWidget *table;
+       GtkWidget *entry;
+       GdkPixbuf *icon;
+       GError    *error = NULL;
+
+       icon = gdk_pixbuf_new_from_file(SAMBA_ICON_PATH,
+                                       &error);
+       if (icon == NULL) {
+               g_print("failed to load logo from %s : %s\n",
+                       SAMBA_ICON_PATH, error->message);
+       }
+
+#if 1
+       image = gtk_image_new_from_file(SAMBA_IMAGE_PATH);
+#else
+       image = gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
+#endif
+
+       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       state->window_main = window;
+
+       gtk_window_set_title(GTK_WINDOW(window), "Samba - Join Domain dialogue");
+       gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600); /* breite * höhe */
+       gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+       gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
+
+       g_signal_connect(G_OBJECT(window), "delete_event",
+                        G_CALLBACK(callback_delete_event), NULL);
+
+       gtk_container_set_border_width(GTK_CONTAINER(window), 10);
+
+       main_vbox = gtk_vbox_new(FALSE, 10);
+       gtk_container_add(GTK_CONTAINER(window), main_vbox);
+
+#if 0
+       gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10);
+       gtk_widget_show(image);
+#endif
+       /* Hbox */
+       hbox = gtk_hbox_new(FALSE, 10);
+       gtk_container_add(GTK_CONTAINER(main_vbox), hbox);
+
+       {
+/*             gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
+               gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
+               gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 10);
+               gtk_widget_show(image);
+
+               /* Label */
+               label = gtk_label_new("Samba uses the following information to identify your computer on the network.");
+               gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+               gtk_widget_set_size_request(GTK_WIDGET(label), 500, 40);
+               gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+               gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+               gtk_widget_show(label);
+       }
+
+       gtk_widget_show(hbox);
+
+       vbox = gtk_vbox_new(FALSE, 0);
+       gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
+       gtk_container_add(GTK_CONTAINER(main_vbox), vbox);
+
+       /* Table */
+       table = gtk_table_new(6, 3, TRUE);
+       gtk_table_set_row_spacings(GTK_TABLE(table), 5);
+       gtk_table_set_col_spacings(GTK_TABLE(table), 5);
+       gtk_container_add(GTK_CONTAINER(vbox), table);
+
+       {
+               /* Label */
+               label = gtk_label_new("Computer description:");
+/*             gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
+               gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
+               gtk_widget_show(label);
+
+               state->button_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
+
+               /* Entry */
+               entry = gtk_entry_new();
+               gtk_entry_set_max_length(GTK_ENTRY(entry), 256);
+               g_signal_connect(G_OBJECT(entry), "changed",
+                                G_CALLBACK(callback_enter_computer_description_and_unlock),
+                                state);
+               g_signal_connect(G_OBJECT(entry), "activate",
+                                G_CALLBACK(callback_apply_continue),
+                                (gpointer)state);
+
+               gtk_entry_set_text(GTK_ENTRY(entry), (char *)state->comment);
+               gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
+               gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 3, 0, 1);
+               gtk_widget_show(entry);
+       }
+
+       /* Label */
+       label = gtk_label_new("For example: \"Samba \%v\".");
+       gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+       gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 1, 2);
+       gtk_widget_show(label);
+
+       /* Label */
+       label = gtk_label_new("Full computer name:");
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+       gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
+       gtk_widget_show(label);
+
+       {
+               /* Label */
+               char *str = NULL;
+               if (state->name_type_initial == NetSetupDomainName) {
+                       asprintf(&str, "%s.%s", state->my_hostname,
+                                state->my_dnsdomain);
+               } else {
+                       asprintf(&str, "%s.", state->my_hostname);
+               }
+
+               label = gtk_label_new(str);
+               SAFE_FREE(str);
+               gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+               gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 2, 3);
+               gtk_widget_show(label);
+       }
+
+       /* Label */
+       if (state->name_type_initial == NetSetupDomainName) {
+               label = gtk_label_new("Domain:");
+       } else {
+               label = gtk_label_new("Workgroup:");
+       }
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+       gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
+       gtk_widget_show(label);
+       state->label_current_name_type = label;
+
+       /* Label */
+       label = gtk_label_new(state->name_buffer_initial);
+       gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+       gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 3, 4);
+       gtk_widget_show(label);
+       state->label_current_name_buffer = label;
+
+       {
+               hbox = gtk_hbox_new(FALSE, 0);
+               gtk_container_add(GTK_CONTAINER(vbox), hbox);
+               label = gtk_label_new("To rename this computer or join a domain, click Change.");
+               gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+
+       }
+
+       /* bbox */
+       bbox = gtk_hbutton_box_new();
+       gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
+       gtk_container_add(GTK_CONTAINER(hbox), bbox);
+       gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+       gtk_box_set_spacing(GTK_BOX(bbox), 10);
+
+       button = gtk_button_new_with_mnemonic("Ch_ange");
+       g_signal_connect(G_OBJECT(button), "clicked",
+                        G_CALLBACK(callback_do_change),
+                        (gpointer)state);
+       gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
+       gtk_widget_show(button);
+
+       /* Label (hidden) */
+       state->label_reboot = gtk_label_new(NULL);
+       gtk_label_set_line_wrap(GTK_LABEL(state->label_reboot), TRUE);
+       gtk_misc_set_alignment(GTK_MISC(state->label_reboot), 0, 0);
+       gtk_box_pack_start(GTK_BOX(vbox), state->label_reboot, TRUE, TRUE, 0);
+       gtk_widget_show(state->label_reboot);
+
+#if 0
+       gtk_box_pack_start(GTK_BOX(vbox),
+          create_bbox(window, TRUE, NULL, 10, 85, 20, GTK_BUTTONBOX_END),
+                     TRUE, TRUE, 5);
+#endif
+       {
+
+               GtkWidget *frame;
+               GtkWidget *bbox2;
+               GtkWidget *button2;
+
+               frame = gtk_frame_new(NULL);
+               bbox2 = gtk_hbutton_box_new();
+
+               gtk_container_set_border_width(GTK_CONTAINER(bbox2), 5);
+               gtk_container_add(GTK_CONTAINER(frame), bbox2);
+
+               /* Set the appearance of the Button Box */
+               gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox2), GTK_BUTTONBOX_END);
+               gtk_box_set_spacing(GTK_BOX(bbox2), 10);
+               /*gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox2), child_w, child_h);*/
+
+               button2 = gtk_button_new_from_stock(GTK_STOCK_OK);
+               gtk_container_add(GTK_CONTAINER(bbox2), button2);
+               g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(callback_do_exit), state);
+
+               button2 = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+               gtk_container_add(GTK_CONTAINER(bbox2), button2);
+               g_signal_connect(G_OBJECT(button2), "clicked",
+                                G_CALLBACK(callback_delete_event),
+                                window);
+
+               gtk_container_add(GTK_CONTAINER(bbox2), state->button_apply);
+               g_signal_connect(G_OBJECT(state->button_apply), "clicked",
+                                G_CALLBACK(callback_apply_description_change),
+                                state);
+               gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
+
+               button2 = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
+               gtk_container_add(GTK_CONTAINER(bbox2), button2);
+               g_signal_connect(G_OBJECT(button2), "clicked",
+                                G_CALLBACK(callback_do_about),
+                                window);
+
+               gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
+       }
+
+       gtk_widget_show_all(window);
+
+       return 0;
+}
+
+static int init_join_state(struct join_state **state)
+{
+       struct join_state *s;
+
+       s = malloc(sizeof(struct join_state));
+       if (!s) {
+               return -1;
+       }
+
+       memset(s, '\0', sizeof(struct join_state));
+
+       *state = s;
+
+       return 0;
+}
+
+static int initialize_join_state(struct join_state *state,
+                                const char *debug_level)
+{
+       struct libnetapi_ctx *ctx = NULL;
+       NET_API_STATUS status = 0;
+
+       status = libnetapi_init(&ctx);
+       if (status) {
+               return status;
+       }
+
+       if (debug_level) {
+               libnetapi_set_debuglevel(ctx, debug_level);
+       }
+
+       {
+               char my_hostname[HOST_NAME_MAX];
+               const char *p = NULL;
+               if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
+                       return -1;
+               }
+
+               state->my_fqdn = strdup(my_hostname);
+               if (!state->my_fqdn) {
+                       return -1;
+               }
+
+               p = strchr(my_hostname, '.');
+               if (p) {
+                       my_hostname[strlen(my_hostname) - strlen(p)] = '\0';
+                       state->my_hostname = strdup(my_hostname);
+                       if (!state->my_hostname) {
+                               return -1;
+                       }
+                       p++;
+                       state->my_dnsdomain = strdup(p);
+                       if (!state->my_dnsdomain) {
+                               return -1;
+                       }
+               }
+       }
+
+       {
+               const char *buffer = NULL;
+               uint16_t type = 0;
+               status = NetGetJoinInformation(NULL, &buffer, &type);
+               if (status) {
+                       return status;
+               }
+               state->name_buffer_initial = (char *)buffer;
+               state->name_type_initial = type;
+       }
+
+       {
+               struct srvsvc_NetSrvInfo1005 *info1005 = NULL;
+               uint8_t *buffer = NULL;
+
+               status = NetServerGetInfo(NULL, 1005, &buffer);
+               if (status) {
+                       return status;
+               }
+
+               info1005 = (struct srvsvc_NetSrvInfo1005 *)buffer;
+
+               state->comment = strdup(info1005->comment);
+               if (!state->comment) {
+                       return -1;
+               }
+       }
+#if 0
+       {
+               struct srvsvc_NetSrvInfo100 *info100 = NULL;
+               uint8_t *buffer = NULL;
+
+               status = NetServerGetInfo(NULL, 100, &buffer);
+               if (status) {
+                       return status;
+               }
+
+               info100 = (struct srvsvc_NetSrvInfo100 *)buffer;
+
+               state->comment = strdup(info100->comment);
+               if (!state->comment) {
+                       return -1;
+               }
+       }
+#endif
+
+       state->ctx = ctx;
+
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       GOptionContext *context = NULL;
+       static const char *debug_level = NULL;
+       struct join_state *state = NULL;
+       GError *error = NULL;
+       int ret = 0;
+
+       static GOptionEntry entries[] = {
+               { "debug", 'd', 0, G_OPTION_ARG_STRING, &debug_level, "Debug level (for samba)", "N" },
+               { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", 0 },
+               { NULL }
+       };
+
+       context = g_option_context_new("- Samba domain join utility");
+       g_option_context_add_main_entries(context, entries, NULL);
+/*     g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); */
+       g_option_context_add_group(context, gtk_get_option_group(TRUE));
+       g_option_context_parse(context, &argc, &argv, &error);
+
+       gtk_init(&argc, &argv);
+       g_set_application_name("Samba");
+
+       ret = init_join_state(&state);
+       if (ret) {
+               return ret;
+       }
+
+       ret = initialize_join_state(state, debug_level);
+       if (ret) {
+               return ret;
+       }
+
+       draw_main_window(state);
+
+       gtk_main();
+
+       do_cleanup(state);
+
+       return 0;
+}
diff --git a/source3/lib/netapi/examples/samba.ico b/source3/lib/netapi/examples/samba.ico
new file mode 100755 (executable)
index 0000000..b70c959
Binary files /dev/null and b/source3/lib/netapi/examples/samba.ico differ