1/* 2 WMI Sample client 3 Copyright (C) 2006 Andrzej Hajda <andrzej.hajda@wp.pl> 4 Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org> 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21#include "includes.h" 22#include "lib/cmdline/popt_common.h" 23#include "librpc/rpc/dcerpc.h" 24#include "librpc/gen_ndr/ndr_oxidresolver.h" 25#include "librpc/gen_ndr/ndr_oxidresolver_c.h" 26#include "librpc/gen_ndr/ndr_dcom.h" 27#include "librpc/gen_ndr/ndr_dcom_c.h" 28#include "librpc/gen_ndr/ndr_remact_c.h" 29#include "librpc/gen_ndr/ndr_epmapper_c.h" 30#include "librpc/gen_ndr/com_dcom.h" 31 32#include "lib/com/dcom/dcom.h" 33#include "lib/com/com.h" 34 35#include "lib/wmi/wmi.h" 36 37struct program_args { 38 char *hostname; 39 char *query; 40 char *ns; 41}; 42 43static void parse_args(int argc, char *argv[], struct program_args *pmyargs) 44{ 45 poptContext pc; 46 int opt, i; 47 48 int argc_new; 49 char **argv_new; 50 51 struct poptOption long_options[] = { 52 POPT_AUTOHELP 53 POPT_COMMON_SAMBA 54 POPT_COMMON_CONNECTION 55 POPT_COMMON_CREDENTIALS 56 POPT_COMMON_VERSION 57 {"namespace", 0, POPT_ARG_STRING, &pmyargs->ns, 0, 58 "WMI namespace, default to root\\cimv2", 0}, 59 POPT_TABLEEND 60 }; 61 62 pc = poptGetContext("wmi", argc, (const char **) argv, 63 long_options, POPT_CONTEXT_KEEP_FIRST); 64 65 poptSetOtherOptionHelp(pc, "//host query\n\nExample: wmic -U [domain/]adminuser%password //host \"select * from Win32_ComputerSystem\""); 66 67 while ((opt = poptGetNextOpt(pc)) != -1) { 68 poptPrintUsage(pc, stdout, 0); 69 poptFreeContext(pc); 70 exit(1); 71 } 72 73 argv_new = discard_const_p(char *, poptGetArgs(pc)); 74 75 argc_new = argc; 76 for (i = 0; i < argc; i++) { 77 if (argv_new[i] == NULL) { 78 argc_new = i; 79 break; 80 } 81 } 82 83 if (argc_new != 3 || argv_new[1][0] != '/' 84 || argv_new[1][1] != '/') { 85 poptPrintUsage(pc, stdout, 0); 86 poptFreeContext(pc); 87 exit(1); 88 } 89 90 pmyargs->hostname = argv_new[1] + 2; 91 pmyargs->query = argv_new[2]; 92 poptFreeContext(pc); 93} 94 95static void escape_string(const char *src, char *dst, int len) 96{ 97 char *p = dst, *end = dst + len - 1; 98 const char *q = src; 99 100 if ( q == NULL) { 101 strncpy( dst, "(null)", len); 102 return; 103 } 104 105 while ( *q && p <= end ) { 106 if ( strchr( "|\\(),", *q)) { 107 *p++ = '\\'; 108 *p++ = *q++; 109 } else if ( *q == '\n' ) { 110 *p++ = '\\'; 111 *p++ = 'n'; 112 q++; 113 } else if ( *q == '\r' ) { 114 *p++ = '\\'; 115 *p++ = 'r'; 116 q++; 117 } else { 118 *p++ = *q++; 119 } 120 } 121 122 *p++ = 0; 123} 124 125#define WERR_CHECK(msg) if (!W_ERROR_IS_OK(result)) { \ 126 DEBUG(0, ("ERROR: %s\n", msg)); \ 127 goto error; \ 128 } else { \ 129 DEBUG(1, ("OK : %s\n", msg)); \ 130 } 131 132#define RETURN_CVAR_ARRAY_STR_START(arr) {\ 133 uint32_t i;\ 134 char *r;\ 135\ 136 if (!arr) {\ 137 return talloc_strdup(mem_ctx, "(null)");\ 138 }\ 139 r = talloc_strdup(mem_ctx, "(");\ 140 for (i = 0; i < arr->count; ++i) { 141 142 143#define RETURN_CVAR_ARRAY_STR_END(fmt, arr, item) \ 144 r = talloc_asprintf_append(r, fmt "%s", item, (i+1 == arr->count)?"":",");\ 145 }\ 146 return talloc_asprintf_append(r, ")");\ 147} 148 149#define RETURN_CVAR_ARRAY_STR(fmt, arr) \ 150 RETURN_CVAR_ARRAY_STR_START(arr) \ 151 RETURN_CVAR_ARRAY_STR_END(fmt, arr, arr->item[i]) 152 153#define RETURN_CVAR_ARRAY_ESCAPED(fmt, arr) \ 154 RETURN_CVAR_ARRAY_STR_START(arr) \ 155 char buf[2048]; \ 156 escape_string( arr->item[i], buf, 2048); \ 157 RETURN_CVAR_ARRAY_STR_END(fmt, arr, buf) 158 159char *string_CIMVAR(TALLOC_CTX *mem_ctx, union CIMVAR *v, enum CIMTYPE_ENUMERATION cimtype) 160{ 161 switch (cimtype) { 162 case CIM_SINT8: return talloc_asprintf(mem_ctx, "%d", v->v_sint8); 163 case CIM_UINT8: return talloc_asprintf(mem_ctx, "%u", v->v_uint8); 164 case CIM_SINT16: return talloc_asprintf(mem_ctx, "%d", v->v_sint16); 165 case CIM_UINT16: return talloc_asprintf(mem_ctx, "%u", v->v_uint16); 166 case CIM_SINT32: return talloc_asprintf(mem_ctx, "%d", v->v_sint32); 167 case CIM_UINT32: return talloc_asprintf(mem_ctx, "%u", v->v_uint32); 168 case CIM_SINT64: return talloc_asprintf(mem_ctx, "%lld", v->v_sint64); 169 case CIM_UINT64: return talloc_asprintf(mem_ctx, "%llu", v->v_sint64); 170 case CIM_REAL32: return talloc_asprintf(mem_ctx, "%f", (double)v->v_uint32); 171 case CIM_REAL64: return talloc_asprintf(mem_ctx, "%f", (double)v->v_uint64); 172 case CIM_BOOLEAN: return talloc_asprintf(mem_ctx, "%s", v->v_boolean?"True":"False"); 173 case CIM_STRING: 174 case CIM_DATETIME: 175 case CIM_REFERENCE: { 176 char buf[2048]; 177 escape_string((char*) v-> v_string, buf, 2048); 178 return talloc_asprintf(mem_ctx, "%s", buf); 179 } 180 case CIM_CHAR16: return talloc_asprintf(mem_ctx, "Unsupported"); 181 case CIM_OBJECT: return talloc_asprintf(mem_ctx, "Unsupported"); 182 case CIM_ARR_SINT8: RETURN_CVAR_ARRAY_STR("%d", v->a_sint8); 183 case CIM_ARR_UINT8: RETURN_CVAR_ARRAY_STR("%u", v->a_uint8); 184 case CIM_ARR_SINT16: RETURN_CVAR_ARRAY_STR("%d", v->a_sint16); 185 case CIM_ARR_UINT16: RETURN_CVAR_ARRAY_STR("%u", v->a_uint16); 186 case CIM_ARR_SINT32: RETURN_CVAR_ARRAY_STR("%d", v->a_sint32); 187 case CIM_ARR_UINT32: RETURN_CVAR_ARRAY_STR("%u", v->a_uint32); 188 case CIM_ARR_SINT64: RETURN_CVAR_ARRAY_STR("%lld", v->a_sint64); 189 case CIM_ARR_UINT64: RETURN_CVAR_ARRAY_STR("%llu", v->a_uint64); 190 case CIM_ARR_REAL32: RETURN_CVAR_ARRAY_STR("%f", v->a_real32); 191 case CIM_ARR_REAL64: RETURN_CVAR_ARRAY_STR("%f", v->a_real64); 192 case CIM_ARR_BOOLEAN: RETURN_CVAR_ARRAY_STR("%d", v->a_boolean); 193 case CIM_ARR_STRING: RETURN_CVAR_ARRAY_ESCAPED("%s", v->a_string); 194 case CIM_ARR_DATETIME: RETURN_CVAR_ARRAY_ESCAPED("%s", v->a_datetime); 195 case CIM_ARR_REFERENCE: RETURN_CVAR_ARRAY_ESCAPED("%s", v->a_reference); 196 default: return talloc_asprintf(mem_ctx, "Unsupported"); 197 } 198} 199 200#undef RETURN_CVAR_ARRAY_STR 201 202int main(int argc, char **argv) 203{ 204 struct program_args args = {}; 205 uint32_t cnt = 5, ret; 206 char *class_name = NULL; 207 WERROR result; 208 NTSTATUS status; 209 struct IWbemServices *pWS = NULL; 210 struct BSTR queryLanguage, query; 211 struct IEnumWbemClassObject *pEnum = NULL; 212 struct com_context *ctx = NULL; 213 214 parse_args(argc, argv, &args); 215 216 wmi_init(&ctx, cmdline_credentials); 217 218 if (!args.ns) 219 args.ns = "root\\cimv2"; 220 result = WBEM_ConnectServer(ctx, args.hostname, args.ns, 0, 0, 0, 0, 0, 0, &pWS); 221 WERR_CHECK("Login to remote object."); 222 223 queryLanguage.data = "WQL"; 224 query.data = args.query; 225 result = IWbemServices_ExecQuery(pWS, ctx, queryLanguage, query, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_ENSURE_LOCATABLE, NULL, &pEnum); 226 WERR_CHECK("WMI query execute."); 227 228 IEnumWbemClassObject_Reset(pEnum, ctx); 229 WERR_CHECK("Reset result of WMI query."); 230 231 do { 232 uint32_t i, j; 233 struct WbemClassObject *co[cnt]; 234 235 result = IEnumWbemClassObject_SmartNext(pEnum, ctx, 0xFFFFFFFF, cnt, co, &ret); 236 /* WERR_BADFUNC is OK, it means only that there is less returned objects than requested */ 237 if (!W_ERROR_EQUAL(result, WERR_BADFUNC)) { 238 WERR_CHECK("Retrieve result data."); 239 } else { 240 DEBUG(1, ("OK : Retrieved less objects than requested (it is normal).\n")); 241 } 242 if (!ret) break; 243 244 for (i = 0; i < ret; ++i) { 245 if (!class_name || strcmp(co[i]->obj_class->__CLASS, class_name)) { 246 if (class_name) talloc_free(class_name); 247 class_name = talloc_strdup(ctx, co[i]->obj_class->__CLASS); 248 printf("CLASS: %s\n", class_name); 249 for (j = 0; j < co[i]->obj_class->__PROPERTY_COUNT; ++j) 250 printf("%s%s", j?"|":"", co[i]->obj_class->properties[j].property.name); 251 printf("\n"); 252 } 253 for (j = 0; j < co[i]->obj_class->__PROPERTY_COUNT; ++j) { 254 char *s; 255 s = string_CIMVAR(ctx, &co[i]->instance->data[j], co[i]->obj_class->properties[j].property.desc->cimtype & CIM_TYPEMASK); 256 printf("%s%s", j?"|":"", s); 257 } 258 printf("\n"); 259 } 260 } while (ret == cnt); 261 talloc_free(ctx); 262 return 0; 263error: 264 status = werror_to_ntstatus(result); 265 fprintf(stderr, "NTSTATUS: %s - %s\n", nt_errstr(status), get_friendly_nt_error_msg(status)); 266 talloc_free(ctx); 267 return 1; 268} 269