summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2000-08-08 06:57:48 +0000
committerGerald Carter <jerry@samba.org>2000-08-08 06:57:48 +0000
commitf296a8d087be261fee51a3a4664685bab1fb5ab1 (patch)
treee8379a6072076c165d40e75d593c09da00c0b379
parent8705fbc42cb3d93a7a56f2673e6e1a19d346abee (diff)
downloadsamba-f296a8d087be261fee51a3a4664685bab1fb5ab1.tar.gz
samba-f296a8d087be261fee51a3a4664685bab1fb5ab1.tar.bz2
samba-f296a8d087be261fee51a3a4664685bab1fb5ab1.zip
All changes related to rpcclient...
- cleaned up some code - Fixed a few memory leaks of my own making - Add AddPrinterDriver(); I'm missing some of the semantics here as the call is done correctly, but I'm not getting all the information right in the DRIVER_INFO_3 struct I think. Will work on it tomorrow some more... --jerry (This used to be commit 3bf9a29f34ee4ade5180c5a0b0b9ff4aca7f0f08)
-rw-r--r--source3/include/rpc_misc.h1
-rwxr-xr-xsource3/include/rpc_spoolss.h23
-rw-r--r--source3/lib/msrpc-client.c4
-rw-r--r--source3/rpc_client/cli_connect.c2
-rw-r--r--source3/rpc_client/cli_spoolss.c52
-rw-r--r--source3/rpc_parse/parse_spoolss.c177
-rw-r--r--source3/rpcclient/cmd_spoolss.c239
7 files changed, 487 insertions, 11 deletions
diff --git a/source3/include/rpc_misc.h b/source3/include/rpc_misc.h
index 6fb2d63ed4..d3e56634a9 100644
--- a/source3/include/rpc_misc.h
+++ b/source3/include/rpc_misc.h
@@ -306,7 +306,6 @@ typedef struct _cli_auth_fns cli_auth_fns;
struct user_creds;
struct cli_connection {
- uint32 num_connections;
char *srv_name;
char *pipe_name;
struct user_creds usr_creds;
diff --git a/source3/include/rpc_spoolss.h b/source3/include/rpc_spoolss.h
index bf854492af..ead4c6cbc1 100755
--- a/source3/include/rpc_spoolss.h
+++ b/source3/include/rpc_spoolss.h
@@ -889,11 +889,34 @@ typedef struct driver_info_3
}
DRIVER_INFO_3;
+typedef struct driver_info_6
+{
+ uint32 version;
+ UNISTR name;
+ UNISTR architecture;
+ UNISTR driverpath;
+ UNISTR datafile;
+ UNISTR configfile;
+ UNISTR helpfile;
+ uint16 *dependentfiles;
+ UNISTR monitorname;
+ UNISTR defaultdatatype;
+ uint16* previousdrivernames;
+ NTTIME driver_date;
+ uint32 driver_version;
+ UNISTR mfgname;
+ UNISTR oem_url;
+ UNISTR hardware_id;
+ UNISTR provider;
+}
+DRIVER_INFO_6;
+
typedef struct driver_info_info
{
DRIVER_INFO_1 *info1;
DRIVER_INFO_2 *info2;
DRIVER_INFO_3 *info3;
+ DRIVER_INFO_6 *info6;
}
PRINTER_DRIVER_CTR;
diff --git a/source3/lib/msrpc-client.c b/source3/lib/msrpc-client.c
index ee3ee0adcc..867094a2c6 100644
--- a/source3/lib/msrpc-client.c
+++ b/source3/lib/msrpc-client.c
@@ -181,7 +181,7 @@ void msrpc_sockopt(struct msrpc_state *msrpc, char *options)
static BOOL msrpc_authenticate(struct msrpc_state *msrpc,
- const struct user_creds *usr)
+ struct user_creds *usr)
{
struct msrpc_state msrpc_redir;
@@ -247,7 +247,7 @@ static BOOL msrpc_authenticate(struct msrpc_state *msrpc,
static BOOL msrpc_init_redirect(struct msrpc_state *msrpc,
const char* pipe_name,
- const struct user_creds *usr)
+ struct user_creds *usr)
{
int sock;
fstring path;
diff --git a/source3/rpc_client/cli_connect.c b/source3/rpc_client/cli_connect.c
index 16279488e8..6dcf92c57d 100644
--- a/source3/rpc_client/cli_connect.c
+++ b/source3/rpc_client/cli_connect.c
@@ -108,7 +108,7 @@ void free_connections(void)
}
static struct cli_connection *cli_con_get(const char *srv_name,
- const char *pipe_name,
+ char *pipe_name,
cli_auth_fns * auth,
void *auth_creds, BOOL reuse)
{
diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c
index 21e87b5799..1bfdf6a468 100644
--- a/source3/rpc_client/cli_spoolss.c
+++ b/source3/rpc_client/cli_spoolss.c
@@ -613,6 +613,7 @@ BOOL spoolss_addprinterex(POLICY_HND *hnd, const char* srv_name, PRINTER_INFO_2
prs_mem_free(&rbuf);
prs_mem_free(&buf );
+ free_spoolss_q_addprinterex(&q_o);
if (mem_ctx)
talloc_destroy(mem_ctx);
@@ -804,4 +805,55 @@ uint32 spoolss_getprinterdriverdir(fstring srv_name, fstring env_name, uint32 le
return r_o.status;
}
+/******************************************************************************
+ AddPrinterDriver()
+ *****************************************************************************/
+uint32 spoolss_addprinterdriver(const char *srv_name, uint32 level, PRINTER_DRIVER_CTR *info)
+{
+ prs_struct rbuf;
+ prs_struct buf;
+ SPOOL_Q_ADDPRINTERDRIVER q_o;
+ SPOOL_R_ADDPRINTERDRIVER r_o;
+ TALLOC_CTX *mem_ctx = NULL;
+ struct cli_connection *con = NULL;
+
+ if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con))
+ return False;
+
+ if ((mem_ctx=talloc_init()) == NULL)
+ {
+ DEBUG(0,("msrpc_spoolss_enum_jobs: talloc_init failed!\n"));
+ return False;
+ }
+ prs_init(&buf , MAX_PDU_FRAG_LEN, 4, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, 4, mem_ctx, UNMARSHALL);
+
+ /* make the ADDPRINTERDRIVER PDU */
+ make_spoolss_q_addprinterdriver(&q_o, srv_name, level, info);
+
+ /* turn the data into an io stream */
+ if (spoolss_io_q_addprinterdriver("", &q_o, &buf, 0) &&
+ rpc_con_pipe_req(con, SPOOLSS_ADDPRINTERDRIVER, &buf, &rbuf))
+ {
+ ZERO_STRUCT(r_o);
+
+ if(!spoolss_io_r_addprinterdriver("", &r_o, &rbuf, 0))
+ {
+ /* report error code */
+ DEBUG(5,("SPOOLSS_ADDPRINTEREX: %s\n", get_nt_error_msg(r_o.status)));
+ }
+ }
+
+
+ prs_mem_free(&rbuf);
+ prs_mem_free(&buf );
+ free_spool_driver_info_3(q_o.info.info_3);
+
+ if (mem_ctx)
+ talloc_destroy(mem_ctx);
+
+ return r_o.status;
+
+}
+
diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c
index 033b680e64..8ebdd55473 100644
--- a/source3/rpc_parse/parse_spoolss.c
+++ b/source3/rpc_parse/parse_spoolss.c
@@ -772,6 +772,41 @@ BOOL make_spoolss_q_addprinterex(SPOOL_Q_ADDPRINTEREX *q_u, const char *srv_name
return True;
}
+
+/*******************************************************************
+ free dynamically allocated members
+ ********************************************************************/
+void free_spoolss_q_addprinterex(SPOOL_Q_ADDPRINTEREX *q_u)
+{
+ switch (q_u->info.level)
+ {
+ case 1:
+ if (q_u->info.info_1 != NULL)
+ {
+ free(q_u->info.info_1);
+ q_u->info.info_1 = NULL;
+ }
+ break;
+ case 2:
+ if (q_u->info.info_2 != NULL)
+ {
+ free(q_u->info.info_2);
+ q_u->info.info_2 = NULL;
+ }
+ break;
+ case 3:
+ if (q_u->info.info_3 != NULL)
+ {
+ free(q_u->info.info_3);
+ q_u->info.info_3 = NULL;
+ }
+ break;
+ }
+
+ return;
+
+}
+
/*******************************************************************
create a SPOOL_PRINTER_INFO_2 stuct from a PRINTER_INFO_2 struct
*******************************************************************/
@@ -898,8 +933,7 @@ BOOL spoolss_io_r_open_printer_ex(char *desc, SPOOL_R_OPEN_PRINTER_EX *r_u, prs_
********************************************************************/
BOOL make_spoolss_q_getprinterdata(SPOOL_Q_GETPRINTERDATA *q_u,
const POLICY_HND *handle,
- const UNISTR2 *valuename,
- uint32 size)
+ UNISTR2 *valuename, uint32 size)
{
if (q_u == NULL) return False;
@@ -4243,7 +4277,143 @@ void free_spool_printer_driver_info_level(SPOOL_PRINTER_DRIVER_INFO_LEVEL *il)
}
/*******************************************************************
-********************************************************************/
+ init a SPOOL_Q_ADDPRINTERDRIVER struct
+ ******************************************************************/
+BOOL make_spoolss_q_addprinterdriver(SPOOL_Q_ADDPRINTERDRIVER *q_u,
+ const char* srv_name, uint32 level,
+ PRINTER_DRIVER_CTR *info)
+{
+ DEBUG(5,("make_spoolss_q_addprinterdriver\n"));
+
+ q_u->server_name_ptr = (srv_name!=NULL)?1:0;
+ init_unistr2(&q_u->server_name, srv_name, strlen(srv_name)+1);
+
+ q_u->level = level;
+
+ q_u->info.level = level;
+ q_u->info.ptr = (info!=NULL)?1:0;
+ switch (level)
+ {
+ /* info level 3 is supported by Windows 95/98,
+ WinNT and Win2k */
+ case 3 :
+ q_u->info.info_3=(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3*)
+ malloc(sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3));
+ make_spool_driver_info_3(q_u->info.info_3, info->info3);
+ break;
+
+ /* info level 6 is supported by WinME and Win2k */
+ case 6:
+ /* WRITEME!! will add later --jerry */
+ break;
+ default:
+ DEBUG(0,("make_spoolss_q_addprinterdriver: Unknown \
+info level [%d]\n", level));
+ break;
+
+ }
+
+ return True;
+}
+
+BOOL make_spool_driver_info_3(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *spool_drv_info,
+ DRIVER_INFO_3 *info3)
+{
+ uint32 len = 0;
+ uint16 *ptr = info3->dependentfiles;
+ BOOL done = False;
+ BOOL null_char = False;
+
+ spool_drv_info->cversion = info3->version;
+ spool_drv_info->name_ptr = (info3->name.buffer!=NULL)?1:0;
+ spool_drv_info->environment_ptr = (info3->architecture.buffer!=NULL)?1:0;
+ spool_drv_info->driverpath_ptr = (info3->driverpath.buffer!=NULL)?1:0;
+ spool_drv_info->datafile_ptr = (info3->datafile.buffer!=NULL)?1:0;
+ spool_drv_info->configfile_ptr = (info3->configfile.buffer!=NULL)?1:0;
+ spool_drv_info->helpfile_ptr = (info3->helpfile.buffer!=NULL)?1:0;
+ spool_drv_info->monitorname_ptr = (info3->monitorname.buffer!=NULL)?1:0;
+ spool_drv_info->defaultdatatype_ptr = (info3->defaultdatatype.buffer!=NULL)?1:0;
+
+ init_unistr2_from_unistr(&spool_drv_info->name, &info3->name);
+ init_unistr2_from_unistr(&spool_drv_info->environment, &info3->architecture);
+ init_unistr2_from_unistr(&spool_drv_info->driverpath, &info3->driverpath);
+ init_unistr2_from_unistr(&spool_drv_info->datafile, &info3->datafile);
+ init_unistr2_from_unistr(&spool_drv_info->configfile, &info3->configfile);
+ init_unistr2_from_unistr(&spool_drv_info->helpfile, &info3->helpfile);
+ init_unistr2_from_unistr(&spool_drv_info->monitorname, &info3->monitorname);
+ init_unistr2_from_unistr(&spool_drv_info->defaultdatatype, &info3->defaultdatatype);
+
+ while (!done)
+ {
+ switch (*ptr)
+ {
+ case 0:
+ /* the null_char BOOL is used to help locate
+ two '\0's back to back */
+ if (null_char)
+ done = True;
+ else
+ null_char = True;
+ break;
+
+ default:
+ null_char = False;
+ ;;
+ break;
+ }
+ len++;
+ ptr++;
+ }
+ spool_drv_info->dependentfiles_ptr = (info3->dependentfiles!=NULL)?1:0;
+ spool_drv_info->dependentfilessize = len;
+ make_spool_buffer5(&spool_drv_info->dependentfiles, len, info3->dependentfiles);
+
+ return True;
+}
+
+void free_spool_driver_info_3 (SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *info)
+{
+ if (info != NULL)
+ {
+ free_spool_buffer5(&info->dependentfiles);
+ }
+
+ return;
+}
+
+/*******************************************************************
+ make a BUFFER5 struct from a uint16*
+ ******************************************************************/
+BOOL make_spool_buffer5(BUFFER5 *buf5, uint32 len, uint16 *src)
+{
+
+ buf5->buf_len = len;
+ if((buf5->buffer=(uint16*)malloc(sizeof(uint16)*len)) == NULL)
+ {
+ DEBUG(0,("make_spool_buffer5: Unable to malloc memory for buffer!\n"));
+ return False;
+ }
+
+ memcpy(buf5->buffer, src, sizeof(uint16)*len);
+
+ return True;
+}
+
+
+void free_spool_buffer5(BUFFER5 *buf)
+{
+ if (buf != NULL)
+ {
+ free(buf->buffer);
+ buf->buffer = NULL;
+ }
+
+ return;
+}
+
+/*******************************************************************
+ fill in the prs_struct for a ADDPRINTERDRIVER request PDU
+ ********************************************************************/
BOOL spoolss_io_q_addprinterdriver(char *desc, SPOOL_Q_ADDPRINTERDRIVER *q_u, prs_struct *ps, int depth)
{
prs_debug(ps, depth, desc, "spoolss_io_q_addprinterdriver");
@@ -4855,6 +5025,7 @@ BOOL spoolss_io_r_setprinterdata(char *desc, SPOOL_R_SETPRINTERDATA *r_u, prs_st
return True;
}
+
/*******************************************************************
********************************************************************/
BOOL convert_specific_param(NT_PRINTER_PARAM **param, const UNISTR2 *value,
diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c
index f79a7042d2..35e09c76e1 100644
--- a/source3/rpcclient/cmd_spoolss.c
+++ b/source3/rpcclient/cmd_spoolss.c
@@ -37,6 +37,49 @@ extern FILE* out_hnd;
extern struct user_creds *usr_creds;
/****************************************************************************
+function to do the mapping between the long architecture name and
+the short one.
+****************************************************************************/
+static BOOL get_short_archi(char *short_archi, char *long_archi)
+{
+ struct table {
+ char *long_archi;
+ char *short_archi;
+ };
+
+ struct table archi_table[]=
+ {
+ {"Windows 4.0", "WIN40" },
+ {"Windows NT x86", "W32X86" },
+ {"Windows NT R4000", "W32MIPS" },
+ {"Windows NT Alpha_AXP", "W32ALPHA" },
+ {"Windows NT PowerPC", "W32PPC" },
+ {NULL, "" }
+ };
+
+ int i=-1;
+
+ DEBUG(107,("Getting architecture dependant directory\n"));
+ do {
+ i++;
+ } while ( (archi_table[i].long_archi!=NULL ) &&
+ StrCaseCmp(long_archi, archi_table[i].long_archi) );
+
+ if (archi_table[i].long_archi==NULL) {
+ DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
+ return FALSE;
+ }
+
+ StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
+
+ DEBUGADD(108,("index: [%d]\n", i));
+ DEBUGADD(108,("long architecture: [%s]\n", long_archi));
+ DEBUGADD(108,("short architecture: [%s]\n", short_archi));
+
+ return TRUE;
+}
+
+/****************************************************************************
nt spoolss query
****************************************************************************/
uint32 cmd_spoolss_enum_printers(struct client_info *info, int argc, char *argv[])
@@ -520,7 +563,7 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[]
/* check (and copy) the command line arguments */
if (argc < 3) {
report(out_hnd, "spooladdprinterex <name> <driver> <port>\n");
- return NT_STATUS_NOPROBLEMO;
+ return NT_STATUS_INVALID_PARAMETER;
}
else
{
@@ -559,7 +602,6 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[]
report (out_hnd, "cmd_spoolss_addprinterex: FAILED to enumerate ports\n");
return NT_STATUS_NOPROBLEMO;
}
-
}
/*
@@ -584,7 +626,6 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[]
return NT_STATUS_NOPROBLEMO;
}
-
/*
* Need to build the PRINTER_INFO_2 struct here.
* I think it would be better only to deal with a PRINTER_INFO_2
@@ -641,6 +682,196 @@ uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[]
********************************************************************************/
uint32 cmd_spoolss_addprinterdriver(struct client_info *info, int argc, char *argv[])
{
+ PRINTER_DRIVER_CTR driver_info;
+ DRIVER_INFO_3 info3;
+ fstring arch;
+ fstring srv_name;
+ uint32 result = NT_STATUS_NO_PROBLEMO;
+
+ /* parse the command arguements */
+ if (argc < 2)
+ {
+ report (out_hnd, "spooladdprinterdriver <arch>\\\n");
+ report (out_hnd, "\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
+ report (out_hnd, "\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
+ report (out_hnd, "\t<Default Data Type>:<Comma Separated list of Files>\n");
- return NT_STATUS_NOPROBLEMO;
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ ZERO_STRUCT(info3);
+
+ /* get the enviorment for the driver */
+ if (!get_short_archi(arch, argv[1]))
+ {
+ report (out_hnd, "Unknown architechture [%s]\n", argv[1]);
+ return NT_STATUS_INVALID_PARAMETER;
+
+ }
+ else
+ {
+ set_drv_info_3_env(&info3, arch);
+ }
+
+ /* fill in the other struct members */
+ if (!init_drv_info_3_members(&info3, argv[2]))
+ {
+ report (out_hnd, "Invalid parameter list.\n");
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ /* get the server name */
+ fstrcpy(srv_name, "\\\\");
+ fstrcat(srv_name, info->dest_host);
+ strupper(srv_name);
+
+ /* call AddPrinterDriver() woth an info level 3 */
+ driver_info.info3 = &info3;
+ if ((result=spoolss_addprinterdriver(srv_name, 3, &driver_info)) != NT_STATUS_NO_PROBLEMO)
+ {
+ report( out_hnd, "spoolss_addprinterdriver: Add Printer failed [%d]\n",
+ result);
+ }
+
+ free_drv_info_3(&info3);
+
+ return result;
}
+
+/*******************************************************************************
+ set the version and environment fields of a DRIVER_INFO_3 struct
+ ******************************************************************************/
+void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
+{
+ if (strcmp(arch, "WIN40") == 0)
+ {
+ info->version = 0;
+ init_unistr(&info->architecture, "Windows 4.0");
+ }
+ else if (strcmp(arch, "W32X86") == 0)
+ {
+ info->version = 2;
+ init_unistr(&info->architecture, "Windows NT x86");
+ }
+ else if (strcmp(arch, "W32MIPS") == 0)
+ {
+ info->version = 2;
+ init_unistr(&info->architecture, "Windows NT R4000");
+ }
+ else if (strcmp(arch, "W32ALPHA") == 0)
+ {
+ info->version = 2;
+ init_unistr(&info->architecture, "Windows NT Alpha_AXP");
+ }
+ else if (strcmp(arch, "W32PPC") == 0)
+ {
+ info->version = 2;
+ init_unistr(&info->architecture, "Windows NT PowerPC");
+ }
+ else
+ {
+ DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
+ }
+
+ return;
+}
+
+/********************************************************************************
+ fill in the members of a DRIVER_INFO_3 struct using a character
+ string in the form of
+ <Long Printer Name>:<Driver File Name>:<Data File Name>:\
+ <Config File Name>:<Help File Name>:<Language Monitor Name>:\
+ <Default Data Type>:<Comma Separated list of Files>
+ *******************************************************************************/
+BOOL init_drv_info_3_members (DRIVER_INFO_3 *info, char *args)
+{
+ char *str, *str2;
+ uint32 len, i;
+
+ /* <Long Printer Name> */
+ if ((str = strtok(args, ":")) == NULL)
+ return False;
+ else
+ init_unistr(&info->name, str);
+
+ /* <Driver File Name> */
+ if ((str = strtok(NULL, ":")) == NULL)
+ return False;
+ else
+ init_unistr(&info->driverpath, str);
+
+ /* <Data File Name > */
+ if ((str = strtok(NULL, ":")) == NULL)
+ return False;
+ else
+ init_unistr(&info->datafile, str);
+
+ /* <Config File Name> */
+ if ((str = strtok(NULL, ":")) == NULL)
+ return False;
+ else
+ init_unistr(&info->configfile, str);
+
+ /* <Help File Name> */
+ if ((str = strtok(NULL, ":")) == NULL)
+ return False;
+ else
+ init_unistr(&info->helpfile, str);
+
+ /* <Language Monitor Name> */
+ if ((str = strtok(NULL, ":")) == NULL)
+ return False;
+ else
+ init_unistr(&info->monitorname, str);
+
+ /* <Default Data Type> */
+ if ((str = strtok(NULL, ":")) == NULL)
+ return False;
+ else
+ init_unistr(&info->defaultdatatype, str);
+
+ /* <Comma Separated List of Dependent Files> */
+ str = strtok(NULL, ":"); /* get the list of dependent files */
+ str2 = str; /* save the beginning of the string */
+ str = strtok(str, ","); /* begin to strip out each filename */
+ len = 0;
+ while (str != NULL)
+ {
+ /* keep a cumlative count of the str lengths */
+ len += strlen(str)+1;
+ str = strtok(NULL, ",");
+ }
+
+ /* allocate the space; add one extra slot for a terminating NULL.
+ Each filename is NULL terminated and the end contains a double
+ NULL */
+ if ((info->dependentfiles=(uint16*)malloc((len+1)*sizeof(uint16))) == NULL)
+ {
+ DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
+ return False;
+ }
+ for (i=0; i<len; i++)
+ {
+ info->dependentfiles[i] = (uint16)str2[i];
+ info->dependentfiles[i] = info->dependentfiles[i] << 8;
+ }
+ info->dependentfiles[len+1] = '\0';
+
+ return True;
+}
+
+/*****************************************************************************
+ free any dynamically allocated members
+ ****************************************************************************/
+void free_drv_info_3 (DRIVER_INFO_3 *info)
+{
+ if (info->dependentfiles != NULL)
+ {
+ free(info->dependentfiles);
+ info->dependentfiles = NULL;
+ }
+
+ return;
+}