18474SJose.Borrego@Sun.COM /* 28474SJose.Borrego@Sun.COM * CDDL HEADER START 38474SJose.Borrego@Sun.COM * 48474SJose.Borrego@Sun.COM * The contents of this file are subject to the terms of the 58474SJose.Borrego@Sun.COM * Common Development and Distribution License (the "License"). 68474SJose.Borrego@Sun.COM * You may not use this file except in compliance with the License. 78474SJose.Borrego@Sun.COM * 88474SJose.Borrego@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 98474SJose.Borrego@Sun.COM * or http://www.opensolaris.org/os/licensing. 108474SJose.Borrego@Sun.COM * See the License for the specific language governing permissions 118474SJose.Borrego@Sun.COM * and limitations under the License. 128474SJose.Borrego@Sun.COM * 138474SJose.Borrego@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 148474SJose.Borrego@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 158474SJose.Borrego@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 168474SJose.Borrego@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 178474SJose.Borrego@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 188474SJose.Borrego@Sun.COM * 198474SJose.Borrego@Sun.COM * CDDL HEADER END 208474SJose.Borrego@Sun.COM */ 218474SJose.Borrego@Sun.COM /* 228474SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 238474SJose.Borrego@Sun.COM * Use is subject to license terms. 248474SJose.Borrego@Sun.COM */ 258474SJose.Borrego@Sun.COM 268474SJose.Borrego@Sun.COM /* 278474SJose.Borrego@Sun.COM * Windows Registry RPC (WINREG) server-side interface. 288474SJose.Borrego@Sun.COM * 298670SJose.Borrego@Sun.COM * The registry is a database with a hierarchical structure similar to 308670SJose.Borrego@Sun.COM * a file system, with keys in place of directories and values in place 318670SJose.Borrego@Sun.COM * of files. The top level keys are known as root keys and each key can 328670SJose.Borrego@Sun.COM * contain subkeys and values. As with directories and sub-directories, 338670SJose.Borrego@Sun.COM * the terms key and subkey are used interchangeably. Values, analogous 348670SJose.Borrego@Sun.COM * to files, contain data. 358474SJose.Borrego@Sun.COM * 368670SJose.Borrego@Sun.COM * A specific subkey can be identifies by its fully qualified name (FQN), 378670SJose.Borrego@Sun.COM * which is analogous to a file system path. In the registry, the key 388670SJose.Borrego@Sun.COM * separator is the '\' character, which is reserved and cannot appear 398670SJose.Borrego@Sun.COM * in key or value names. Registry names are case-insensitive. 408670SJose.Borrego@Sun.COM * 418670SJose.Borrego@Sun.COM * For example: HKEY_LOCAL_MACHINE\System\CurrentControlSet 428670SJose.Borrego@Sun.COM * 439914Samw@Sun.COM * The HKEY_LOCAL_MACHINE root key contains a subkey called System, and 448670SJose.Borrego@Sun.COM * System contains a subkey called CurrentControlSet. 458670SJose.Borrego@Sun.COM * 468670SJose.Borrego@Sun.COM * The WINREG RPC interface returns Win32 error codes. 478474SJose.Borrego@Sun.COM */ 488474SJose.Borrego@Sun.COM 498474SJose.Borrego@Sun.COM #include <sys/utsname.h> 508474SJose.Borrego@Sun.COM #include <strings.h> 518474SJose.Borrego@Sun.COM 528474SJose.Borrego@Sun.COM #include <smbsrv/libsmb.h> 538474SJose.Borrego@Sun.COM #include <smbsrv/ntstatus.h> 548474SJose.Borrego@Sun.COM #include <smbsrv/nterror.h> 558474SJose.Borrego@Sun.COM #include <smbsrv/nmpipes.h> 568474SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h> 578474SJose.Borrego@Sun.COM #include <smbsrv/ndl/winreg.ndl> 588474SJose.Borrego@Sun.COM 598474SJose.Borrego@Sun.COM /* 608474SJose.Borrego@Sun.COM * List of supported registry keys (case-insensitive). 618474SJose.Borrego@Sun.COM */ 628474SJose.Borrego@Sun.COM static char *winreg_keys[] = { 639914Samw@Sun.COM "HKLM", 649914Samw@Sun.COM "HKU", 659914Samw@Sun.COM "HKLM\\SOFTWARE", 669914Samw@Sun.COM "HKLM\\SYSTEM", 6710504SKeyur.Desai@Sun.COM "Application", 6810504SKeyur.Desai@Sun.COM "Security", 699914Samw@Sun.COM "System", 709914Samw@Sun.COM "CurrentControlSet", 718474SJose.Borrego@Sun.COM "System\\CurrentControlSet\\Services\\Eventlog", 728670SJose.Borrego@Sun.COM "System\\CurrentControlSet\\Services\\Eventlog\\Application", 738670SJose.Borrego@Sun.COM "System\\CurrentControlSet\\Services\\Eventlog\\Security", 748474SJose.Borrego@Sun.COM "System\\CurrentControlSet\\Services\\Eventlog\\System", 758474SJose.Borrego@Sun.COM "System\\CurrentControlSet\\Control\\ProductOptions", 769914Samw@Sun.COM "SOFTWARE", 778474SJose.Borrego@Sun.COM "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" 788474SJose.Borrego@Sun.COM }; 798474SJose.Borrego@Sun.COM 808474SJose.Borrego@Sun.COM typedef struct winreg_subkey { 818474SJose.Borrego@Sun.COM list_node_t sk_lnd; 828474SJose.Borrego@Sun.COM ndr_hdid_t sk_handle; 838474SJose.Borrego@Sun.COM char sk_name[MAXPATHLEN]; 848474SJose.Borrego@Sun.COM boolean_t sk_predefined; 858474SJose.Borrego@Sun.COM } winreg_subkey_t; 868474SJose.Borrego@Sun.COM 878474SJose.Borrego@Sun.COM typedef struct winreg_keylist { 888474SJose.Borrego@Sun.COM list_t kl_list; 898474SJose.Borrego@Sun.COM int kl_count; 908474SJose.Borrego@Sun.COM } winreg_keylist_t; 918474SJose.Borrego@Sun.COM 928474SJose.Borrego@Sun.COM static winreg_keylist_t winreg_keylist; 938474SJose.Borrego@Sun.COM 948474SJose.Borrego@Sun.COM static boolean_t winreg_key_has_subkey(const char *); 958670SJose.Borrego@Sun.COM static char *winreg_enum_subkey(ndr_xa_t *, const char *, uint32_t); 968474SJose.Borrego@Sun.COM static char *winreg_lookup_value(const char *); 978474SJose.Borrego@Sun.COM 988670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCR(void *, ndr_xa_t *); 998670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCU(void *, ndr_xa_t *); 1008474SJose.Borrego@Sun.COM static int winreg_s_OpenHKLM(void *, ndr_xa_t *); 1018670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPD(void *, ndr_xa_t *); 1028670SJose.Borrego@Sun.COM static int winreg_s_OpenHKU(void *, ndr_xa_t *); 1038670SJose.Borrego@Sun.COM static int winreg_s_OpenHKCC(void *, ndr_xa_t *); 1048670SJose.Borrego@Sun.COM static int winreg_s_OpenHKDD(void *, ndr_xa_t *); 1058670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPT(void *, ndr_xa_t *); 1068670SJose.Borrego@Sun.COM static int winreg_s_OpenHKPN(void *, ndr_xa_t *); 1078670SJose.Borrego@Sun.COM static int winreg_s_OpenHK(void *, ndr_xa_t *, const char *); 1088474SJose.Borrego@Sun.COM static int winreg_s_Close(void *, ndr_xa_t *); 1098474SJose.Borrego@Sun.COM static int winreg_s_CreateKey(void *, ndr_xa_t *); 1108474SJose.Borrego@Sun.COM static int winreg_s_DeleteKey(void *, ndr_xa_t *); 1118474SJose.Borrego@Sun.COM static int winreg_s_DeleteValue(void *, ndr_xa_t *); 1128474SJose.Borrego@Sun.COM static int winreg_s_EnumKey(void *, ndr_xa_t *); 1138474SJose.Borrego@Sun.COM static int winreg_s_EnumValue(void *, ndr_xa_t *); 1148474SJose.Borrego@Sun.COM static int winreg_s_FlushKey(void *, ndr_xa_t *); 1158474SJose.Borrego@Sun.COM static int winreg_s_GetKeySec(void *, ndr_xa_t *); 1168474SJose.Borrego@Sun.COM static int winreg_s_NotifyChange(void *, ndr_xa_t *); 1178474SJose.Borrego@Sun.COM static int winreg_s_OpenKey(void *, ndr_xa_t *); 1188474SJose.Borrego@Sun.COM static int winreg_s_QueryKey(void *, ndr_xa_t *); 1198474SJose.Borrego@Sun.COM static int winreg_s_QueryValue(void *, ndr_xa_t *); 1208474SJose.Borrego@Sun.COM static int winreg_s_SetKeySec(void *, ndr_xa_t *); 1218474SJose.Borrego@Sun.COM static int winreg_s_CreateValue(void *, ndr_xa_t *); 1228474SJose.Borrego@Sun.COM static int winreg_s_Shutdown(void *, ndr_xa_t *); 1238474SJose.Borrego@Sun.COM static int winreg_s_AbortShutdown(void *, ndr_xa_t *); 1248474SJose.Borrego@Sun.COM static int winreg_s_GetVersion(void *, ndr_xa_t *); 1258474SJose.Borrego@Sun.COM 1268474SJose.Borrego@Sun.COM static ndr_stub_table_t winreg_stub_table[] = { 1278670SJose.Borrego@Sun.COM { winreg_s_OpenHKCR, WINREG_OPNUM_OpenHKCR }, 1288670SJose.Borrego@Sun.COM { winreg_s_OpenHKCU, WINREG_OPNUM_OpenHKCU }, 1298474SJose.Borrego@Sun.COM { winreg_s_OpenHKLM, WINREG_OPNUM_OpenHKLM }, 1308670SJose.Borrego@Sun.COM { winreg_s_OpenHKPD, WINREG_OPNUM_OpenHKPD }, 1318670SJose.Borrego@Sun.COM { winreg_s_OpenHKU, WINREG_OPNUM_OpenHKUsers }, 1328474SJose.Borrego@Sun.COM { winreg_s_Close, WINREG_OPNUM_Close }, 1338474SJose.Borrego@Sun.COM { winreg_s_CreateKey, WINREG_OPNUM_CreateKey }, 1348474SJose.Borrego@Sun.COM { winreg_s_DeleteKey, WINREG_OPNUM_DeleteKey }, 1358474SJose.Borrego@Sun.COM { winreg_s_DeleteValue, WINREG_OPNUM_DeleteValue }, 1368474SJose.Borrego@Sun.COM { winreg_s_EnumKey, WINREG_OPNUM_EnumKey }, 1378474SJose.Borrego@Sun.COM { winreg_s_EnumValue, WINREG_OPNUM_EnumValue }, 1388474SJose.Borrego@Sun.COM { winreg_s_FlushKey, WINREG_OPNUM_FlushKey }, 1398474SJose.Borrego@Sun.COM { winreg_s_GetKeySec, WINREG_OPNUM_GetKeySec }, 1408474SJose.Borrego@Sun.COM { winreg_s_NotifyChange, WINREG_OPNUM_NotifyChange }, 1418474SJose.Borrego@Sun.COM { winreg_s_OpenKey, WINREG_OPNUM_OpenKey }, 1428474SJose.Borrego@Sun.COM { winreg_s_QueryKey, WINREG_OPNUM_QueryKey }, 1438474SJose.Borrego@Sun.COM { winreg_s_QueryValue, WINREG_OPNUM_QueryValue }, 1448474SJose.Borrego@Sun.COM { winreg_s_SetKeySec, WINREG_OPNUM_SetKeySec }, 1458474SJose.Borrego@Sun.COM { winreg_s_CreateValue, WINREG_OPNUM_CreateValue }, 1468474SJose.Borrego@Sun.COM { winreg_s_Shutdown, WINREG_OPNUM_Shutdown }, 1478474SJose.Borrego@Sun.COM { winreg_s_AbortShutdown, WINREG_OPNUM_AbortShutdown }, 1488474SJose.Borrego@Sun.COM { winreg_s_GetVersion, WINREG_OPNUM_GetVersion }, 1498670SJose.Borrego@Sun.COM { winreg_s_OpenHKCC, WINREG_OPNUM_OpenHKCC }, 1508670SJose.Borrego@Sun.COM { winreg_s_OpenHKDD, WINREG_OPNUM_OpenHKDD }, 1518670SJose.Borrego@Sun.COM { winreg_s_OpenHKPT, WINREG_OPNUM_OpenHKPT }, 1528670SJose.Borrego@Sun.COM { winreg_s_OpenHKPN, WINREG_OPNUM_OpenHKPN }, 1538474SJose.Borrego@Sun.COM {0} 1548474SJose.Borrego@Sun.COM }; 1558474SJose.Borrego@Sun.COM 1568474SJose.Borrego@Sun.COM static ndr_service_t winreg_service = { 1578474SJose.Borrego@Sun.COM "Winreg", /* name */ 1588474SJose.Borrego@Sun.COM "Windows Registry", /* desc */ 1598474SJose.Borrego@Sun.COM "\\winreg", /* endpoint */ 1608474SJose.Borrego@Sun.COM PIPE_WINREG, /* sec_addr_port */ 1618474SJose.Borrego@Sun.COM "338cd001-2244-31f1-aaaa-900038001003", 1, /* abstract */ 1628474SJose.Borrego@Sun.COM NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */ 1638474SJose.Borrego@Sun.COM 0, /* no bind_instance_size */ 1648474SJose.Borrego@Sun.COM 0, /* no bind_req() */ 1658474SJose.Borrego@Sun.COM 0, /* no unbind_and_close() */ 1668474SJose.Borrego@Sun.COM 0, /* use generic_call_stub() */ 1678474SJose.Borrego@Sun.COM &TYPEINFO(winreg_interface), /* interface ti */ 1688474SJose.Borrego@Sun.COM winreg_stub_table /* stub_table */ 1698474SJose.Borrego@Sun.COM }; 1708474SJose.Borrego@Sun.COM 1718474SJose.Borrego@Sun.COM static char winreg_sysname[SYS_NMLN]; 1728474SJose.Borrego@Sun.COM 1738474SJose.Borrego@Sun.COM /* 1748474SJose.Borrego@Sun.COM * winreg_initialize 1758474SJose.Borrego@Sun.COM * 1768474SJose.Borrego@Sun.COM * Initialize and register the WINREG RPC interface with the RPC runtime 1778474SJose.Borrego@Sun.COM * library. It must be called in order to use either the client side 1788474SJose.Borrego@Sun.COM * or the server side functions. 1798474SJose.Borrego@Sun.COM */ 1808474SJose.Borrego@Sun.COM void 1818474SJose.Borrego@Sun.COM winreg_initialize(void) 1828474SJose.Borrego@Sun.COM { 1838474SJose.Borrego@Sun.COM winreg_subkey_t *key; 1848474SJose.Borrego@Sun.COM struct utsname name; 1858474SJose.Borrego@Sun.COM char *sysname; 1868474SJose.Borrego@Sun.COM int i; 1878474SJose.Borrego@Sun.COM 1888474SJose.Borrego@Sun.COM list_create(&winreg_keylist.kl_list, sizeof (winreg_subkey_t), 1898474SJose.Borrego@Sun.COM offsetof(winreg_subkey_t, sk_lnd)); 1908474SJose.Borrego@Sun.COM winreg_keylist.kl_count = 0; 1918474SJose.Borrego@Sun.COM 1928474SJose.Borrego@Sun.COM for (i = 0; i < sizeof (winreg_keys)/sizeof (winreg_keys[0]); ++i) { 1938474SJose.Borrego@Sun.COM if ((key = malloc(sizeof (winreg_subkey_t))) != NULL) { 1948474SJose.Borrego@Sun.COM bzero(key, sizeof (winreg_subkey_t)); 1958474SJose.Borrego@Sun.COM (void) strlcpy(key->sk_name, winreg_keys[i], 1968474SJose.Borrego@Sun.COM MAXPATHLEN); 1978474SJose.Borrego@Sun.COM key->sk_predefined = B_TRUE; 1988474SJose.Borrego@Sun.COM list_insert_tail(&winreg_keylist.kl_list, key); 1998474SJose.Borrego@Sun.COM ++winreg_keylist.kl_count; 2008474SJose.Borrego@Sun.COM } 2018474SJose.Borrego@Sun.COM } 2028474SJose.Borrego@Sun.COM 2038474SJose.Borrego@Sun.COM if (uname(&name) < 0) 2048474SJose.Borrego@Sun.COM sysname = "Solaris"; 2058474SJose.Borrego@Sun.COM else 2068474SJose.Borrego@Sun.COM sysname = name.sysname; 2078474SJose.Borrego@Sun.COM 2088474SJose.Borrego@Sun.COM (void) strlcpy(winreg_sysname, sysname, SYS_NMLN); 2098474SJose.Borrego@Sun.COM (void) ndr_svc_register(&winreg_service); 2108474SJose.Borrego@Sun.COM } 2118474SJose.Borrego@Sun.COM 2128670SJose.Borrego@Sun.COM static int 2138670SJose.Borrego@Sun.COM winreg_s_OpenHKCR(void *arg, ndr_xa_t *mxa) 2148670SJose.Borrego@Sun.COM { 2158670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKCR")); 2168670SJose.Borrego@Sun.COM } 2178670SJose.Borrego@Sun.COM 2188474SJose.Borrego@Sun.COM static int 2198670SJose.Borrego@Sun.COM winreg_s_OpenHKCU(void *arg, ndr_xa_t *mxa) 2208670SJose.Borrego@Sun.COM { 2218670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKCU")); 2228670SJose.Borrego@Sun.COM } 2238670SJose.Borrego@Sun.COM 2248670SJose.Borrego@Sun.COM static int 2258670SJose.Borrego@Sun.COM winreg_s_OpenHKLM(void *arg, ndr_xa_t *mxa) 2268670SJose.Borrego@Sun.COM { 2278670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKLM")); 2288670SJose.Borrego@Sun.COM } 2298670SJose.Borrego@Sun.COM 2308670SJose.Borrego@Sun.COM static int 2318670SJose.Borrego@Sun.COM winreg_s_OpenHKPD(void *arg, ndr_xa_t *mxa) 2328474SJose.Borrego@Sun.COM { 2338670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKPD")); 2348670SJose.Borrego@Sun.COM } 2358670SJose.Borrego@Sun.COM 2368670SJose.Borrego@Sun.COM static int 2378670SJose.Borrego@Sun.COM winreg_s_OpenHKU(void *arg, ndr_xa_t *mxa) 2388670SJose.Borrego@Sun.COM { 2398670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKU")); 2408670SJose.Borrego@Sun.COM } 2418670SJose.Borrego@Sun.COM 2428670SJose.Borrego@Sun.COM static int 2438670SJose.Borrego@Sun.COM winreg_s_OpenHKCC(void *arg, ndr_xa_t *mxa) 2448670SJose.Borrego@Sun.COM { 2458670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKCC")); 2468670SJose.Borrego@Sun.COM } 2478474SJose.Borrego@Sun.COM 2488670SJose.Borrego@Sun.COM static int 2498670SJose.Borrego@Sun.COM winreg_s_OpenHKDD(void *arg, ndr_xa_t *mxa) 2508670SJose.Borrego@Sun.COM { 2518670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKDD")); 2528670SJose.Borrego@Sun.COM } 2538474SJose.Borrego@Sun.COM 2548670SJose.Borrego@Sun.COM static int 2558670SJose.Borrego@Sun.COM winreg_s_OpenHKPT(void *arg, ndr_xa_t *mxa) 2568670SJose.Borrego@Sun.COM { 2578670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKPT")); 2588670SJose.Borrego@Sun.COM } 2598670SJose.Borrego@Sun.COM 2608670SJose.Borrego@Sun.COM static int 2618670SJose.Borrego@Sun.COM winreg_s_OpenHKPN(void *arg, ndr_xa_t *mxa) 2628670SJose.Borrego@Sun.COM { 2638670SJose.Borrego@Sun.COM return (winreg_s_OpenHK(arg, mxa, "HKPN")); 2648474SJose.Borrego@Sun.COM } 2658474SJose.Borrego@Sun.COM 2668474SJose.Borrego@Sun.COM /* 2678670SJose.Borrego@Sun.COM * winreg_s_OpenHK 2688474SJose.Borrego@Sun.COM * 2698670SJose.Borrego@Sun.COM * Common code to open root HKEYs. 2708474SJose.Borrego@Sun.COM */ 2718474SJose.Borrego@Sun.COM static int 2728670SJose.Borrego@Sun.COM winreg_s_OpenHK(void *arg, ndr_xa_t *mxa, const char *hkey) 2738474SJose.Borrego@Sun.COM { 2748670SJose.Borrego@Sun.COM struct winreg_OpenHKCR *param = arg; 2758474SJose.Borrego@Sun.COM ndr_hdid_t *id; 2768670SJose.Borrego@Sun.COM char *dupkey; 2778474SJose.Borrego@Sun.COM 2788670SJose.Borrego@Sun.COM if ((dupkey = strdup(hkey)) == NULL) { 2798474SJose.Borrego@Sun.COM bzero(¶m->handle, sizeof (winreg_handle_t)); 2808670SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 2818670SJose.Borrego@Sun.COM return (NDR_DRC_OK); 2828474SJose.Borrego@Sun.COM } 2838474SJose.Borrego@Sun.COM 2848670SJose.Borrego@Sun.COM if ((id = ndr_hdalloc(mxa, dupkey)) == NULL) { 2858670SJose.Borrego@Sun.COM free(dupkey); 2868474SJose.Borrego@Sun.COM bzero(¶m->handle, sizeof (winreg_handle_t)); 2878474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 2888474SJose.Borrego@Sun.COM } else { 2898474SJose.Borrego@Sun.COM bcopy(id, ¶m->handle, sizeof (winreg_handle_t)); 2908474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 2918474SJose.Borrego@Sun.COM } 2928474SJose.Borrego@Sun.COM 2938474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 2948474SJose.Borrego@Sun.COM } 2958474SJose.Borrego@Sun.COM 2968474SJose.Borrego@Sun.COM /* 2978474SJose.Borrego@Sun.COM * winreg_s_Close 2988474SJose.Borrego@Sun.COM * 2998474SJose.Borrego@Sun.COM * This is a request to close the WINREG interface specified by the 3008474SJose.Borrego@Sun.COM * handle. We don't track handles (yet), so just zero out the handle 3018474SJose.Borrego@Sun.COM * and return NDR_DRC_OK. Setting the handle to zero appears to be 3028474SJose.Borrego@Sun.COM * standard behaviour. 3038474SJose.Borrego@Sun.COM */ 3048474SJose.Borrego@Sun.COM static int 3058474SJose.Borrego@Sun.COM winreg_s_Close(void *arg, ndr_xa_t *mxa) 3068474SJose.Borrego@Sun.COM { 3078474SJose.Borrego@Sun.COM struct winreg_Close *param = arg; 3088474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 3098670SJose.Borrego@Sun.COM ndr_handle_t *hd; 3108670SJose.Borrego@Sun.COM 3118670SJose.Borrego@Sun.COM if ((hd = ndr_hdlookup(mxa, id)) != NULL) { 3128670SJose.Borrego@Sun.COM free(hd->nh_data); 3138670SJose.Borrego@Sun.COM hd->nh_data = NULL; 3148670SJose.Borrego@Sun.COM } 3158474SJose.Borrego@Sun.COM 3168474SJose.Borrego@Sun.COM ndr_hdfree(mxa, id); 3178474SJose.Borrego@Sun.COM 3188474SJose.Borrego@Sun.COM bzero(¶m->result_handle, sizeof (winreg_handle_t)); 3198474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 3208474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3218474SJose.Borrego@Sun.COM } 3228474SJose.Borrego@Sun.COM 3238474SJose.Borrego@Sun.COM /* 3248474SJose.Borrego@Sun.COM * winreg_s_CreateKey 3258474SJose.Borrego@Sun.COM */ 3268474SJose.Borrego@Sun.COM static int 3278474SJose.Borrego@Sun.COM winreg_s_CreateKey(void *arg, ndr_xa_t *mxa) 3288474SJose.Borrego@Sun.COM { 3298474SJose.Borrego@Sun.COM struct winreg_CreateKey *param = arg; 3308474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 3318474SJose.Borrego@Sun.COM ndr_handle_t *hd; 3328474SJose.Borrego@Sun.COM winreg_subkey_t *key; 3338474SJose.Borrego@Sun.COM char *subkey; 3348670SJose.Borrego@Sun.COM char *dupkey; 3358474SJose.Borrego@Sun.COM DWORD *action; 3368474SJose.Borrego@Sun.COM 3378474SJose.Borrego@Sun.COM subkey = (char *)param->subkey.str; 3388474SJose.Borrego@Sun.COM 3398474SJose.Borrego@Sun.COM if (!ndr_is_admin(mxa) || (subkey == NULL)) { 3408474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_CreateKey)); 3418474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 3428474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3438474SJose.Borrego@Sun.COM } 3448474SJose.Borrego@Sun.COM 3458474SJose.Borrego@Sun.COM hd = ndr_hdlookup(mxa, id); 3468474SJose.Borrego@Sun.COM if (hd == NULL) { 3478474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_CreateKey)); 3488474SJose.Borrego@Sun.COM param->status = ERROR_INVALID_HANDLE; 3498474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3508474SJose.Borrego@Sun.COM } 3518474SJose.Borrego@Sun.COM 3528474SJose.Borrego@Sun.COM if ((action = NDR_NEW(mxa, DWORD)) == NULL) { 3538474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_CreateKey)); 3548474SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 3558474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3568474SJose.Borrego@Sun.COM } 3578474SJose.Borrego@Sun.COM 3588474SJose.Borrego@Sun.COM if (list_is_empty(&winreg_keylist.kl_list)) 3598474SJose.Borrego@Sun.COM goto new_key; 3608474SJose.Borrego@Sun.COM 3618474SJose.Borrego@Sun.COM /* 3628474SJose.Borrego@Sun.COM * Check for an existing key. 3638474SJose.Borrego@Sun.COM */ 3648474SJose.Borrego@Sun.COM key = list_head(&winreg_keylist.kl_list); 3658474SJose.Borrego@Sun.COM do { 3668474SJose.Borrego@Sun.COM if (strcasecmp(subkey, key->sk_name) == 0) { 3678474SJose.Borrego@Sun.COM bcopy(&key->sk_handle, ¶m->result_handle, 3688474SJose.Borrego@Sun.COM sizeof (winreg_handle_t)); 3698474SJose.Borrego@Sun.COM *action = WINREG_ACTION_EXISTING_KEY; 3708474SJose.Borrego@Sun.COM param->action = action; 3718474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 3728474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3738474SJose.Borrego@Sun.COM } 3748474SJose.Borrego@Sun.COM } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 3758474SJose.Borrego@Sun.COM 3768474SJose.Borrego@Sun.COM new_key: 3778474SJose.Borrego@Sun.COM /* 3788474SJose.Borrego@Sun.COM * Create a new key. 3798474SJose.Borrego@Sun.COM */ 3808670SJose.Borrego@Sun.COM if ((dupkey = strdup(subkey)) == NULL) { 3818670SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_CreateKey)); 3828670SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 3838670SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3848670SJose.Borrego@Sun.COM } 3858670SJose.Borrego@Sun.COM 3868670SJose.Borrego@Sun.COM id = ndr_hdalloc(mxa, dupkey); 3878474SJose.Borrego@Sun.COM key = malloc(sizeof (winreg_subkey_t)); 3888474SJose.Borrego@Sun.COM 3898474SJose.Borrego@Sun.COM if ((id == NULL) || (key == NULL)) { 3908670SJose.Borrego@Sun.COM free(dupkey); 3918474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_CreateKey)); 3928474SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 3938474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 3948474SJose.Borrego@Sun.COM } 3958474SJose.Borrego@Sun.COM 3968474SJose.Borrego@Sun.COM bcopy(id, &key->sk_handle, sizeof (ndr_hdid_t)); 3978474SJose.Borrego@Sun.COM (void) strlcpy(key->sk_name, subkey, MAXPATHLEN); 3988474SJose.Borrego@Sun.COM key->sk_predefined = B_FALSE; 3998474SJose.Borrego@Sun.COM list_insert_tail(&winreg_keylist.kl_list, key); 4008474SJose.Borrego@Sun.COM ++winreg_keylist.kl_count; 4018474SJose.Borrego@Sun.COM 4028474SJose.Borrego@Sun.COM bcopy(id, ¶m->result_handle, sizeof (winreg_handle_t)); 4038474SJose.Borrego@Sun.COM *action = WINREG_ACTION_NEW_KEY; 4048474SJose.Borrego@Sun.COM param->action = action; 4058474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 4068474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 4078474SJose.Borrego@Sun.COM } 4088474SJose.Borrego@Sun.COM 4098474SJose.Borrego@Sun.COM /* 4108474SJose.Borrego@Sun.COM * winreg_s_DeleteKey 4118474SJose.Borrego@Sun.COM */ 4128474SJose.Borrego@Sun.COM static int 4138474SJose.Borrego@Sun.COM winreg_s_DeleteKey(void *arg, ndr_xa_t *mxa) 4148474SJose.Borrego@Sun.COM { 4158474SJose.Borrego@Sun.COM struct winreg_DeleteKey *param = arg; 4168474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 4178670SJose.Borrego@Sun.COM ndr_handle_t *hd; 4188474SJose.Borrego@Sun.COM winreg_subkey_t *key; 4198474SJose.Borrego@Sun.COM char *subkey; 4208474SJose.Borrego@Sun.COM 4218474SJose.Borrego@Sun.COM subkey = (char *)param->subkey.str; 4228474SJose.Borrego@Sun.COM 4238474SJose.Borrego@Sun.COM if (!ndr_is_admin(mxa) || (subkey == NULL)) { 4248474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 4258474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 4268474SJose.Borrego@Sun.COM } 4278474SJose.Borrego@Sun.COM 4288474SJose.Borrego@Sun.COM if ((ndr_hdlookup(mxa, id) == NULL) || 4298474SJose.Borrego@Sun.COM list_is_empty(&winreg_keylist.kl_list) || 4308474SJose.Borrego@Sun.COM winreg_key_has_subkey(subkey)) { 4318474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 4328474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 4338474SJose.Borrego@Sun.COM } 4348474SJose.Borrego@Sun.COM 4358474SJose.Borrego@Sun.COM key = list_head(&winreg_keylist.kl_list); 4368474SJose.Borrego@Sun.COM do { 4378474SJose.Borrego@Sun.COM if (strcasecmp(subkey, key->sk_name) == 0) { 4388474SJose.Borrego@Sun.COM if (key->sk_predefined == B_TRUE) { 4398474SJose.Borrego@Sun.COM /* Predefined keys cannot be deleted */ 4408474SJose.Borrego@Sun.COM break; 4418474SJose.Borrego@Sun.COM } 4428474SJose.Borrego@Sun.COM 4438474SJose.Borrego@Sun.COM list_remove(&winreg_keylist.kl_list, key); 4448474SJose.Borrego@Sun.COM --winreg_keylist.kl_count; 4458670SJose.Borrego@Sun.COM 4468670SJose.Borrego@Sun.COM hd = ndr_hdlookup(mxa, &key->sk_handle); 4478670SJose.Borrego@Sun.COM if (hd != NULL) { 4488670SJose.Borrego@Sun.COM free(hd->nh_data); 4498670SJose.Borrego@Sun.COM hd->nh_data = NULL; 4508670SJose.Borrego@Sun.COM } 4518670SJose.Borrego@Sun.COM 4528474SJose.Borrego@Sun.COM ndr_hdfree(mxa, &key->sk_handle); 4538474SJose.Borrego@Sun.COM free(key); 4548474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 4558474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 4568474SJose.Borrego@Sun.COM } 4578474SJose.Borrego@Sun.COM } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 4588474SJose.Borrego@Sun.COM 4598474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 4608474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 4618474SJose.Borrego@Sun.COM } 4628474SJose.Borrego@Sun.COM 4638474SJose.Borrego@Sun.COM static boolean_t 4648474SJose.Borrego@Sun.COM winreg_key_has_subkey(const char *subkey) 4658474SJose.Borrego@Sun.COM { 4668474SJose.Borrego@Sun.COM winreg_subkey_t *key; 4678474SJose.Borrego@Sun.COM int keylen; 4688474SJose.Borrego@Sun.COM 4698474SJose.Borrego@Sun.COM if (list_is_empty(&winreg_keylist.kl_list)) 4708474SJose.Borrego@Sun.COM return (B_FALSE); 4718474SJose.Borrego@Sun.COM 4728474SJose.Borrego@Sun.COM keylen = strlen(subkey); 4738474SJose.Borrego@Sun.COM 4748474SJose.Borrego@Sun.COM key = list_head(&winreg_keylist.kl_list); 4758474SJose.Borrego@Sun.COM do { 4768474SJose.Borrego@Sun.COM if (strncasecmp(subkey, key->sk_name, keylen) == 0) { 4778474SJose.Borrego@Sun.COM /* 4788474SJose.Borrego@Sun.COM * Potential match. If sk_name is longer than 4798474SJose.Borrego@Sun.COM * subkey, then sk_name is a subkey of our key. 4808474SJose.Borrego@Sun.COM */ 4818474SJose.Borrego@Sun.COM if (keylen < strlen(key->sk_name)) 4828474SJose.Borrego@Sun.COM return (B_TRUE); 4838474SJose.Borrego@Sun.COM } 4848474SJose.Borrego@Sun.COM } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 4858474SJose.Borrego@Sun.COM 4868474SJose.Borrego@Sun.COM return (B_FALSE); 4878474SJose.Borrego@Sun.COM } 4888474SJose.Borrego@Sun.COM 4898474SJose.Borrego@Sun.COM static char * 4908670SJose.Borrego@Sun.COM winreg_enum_subkey(ndr_xa_t *mxa, const char *subkey, uint32_t index) 4918474SJose.Borrego@Sun.COM { 4928474SJose.Borrego@Sun.COM winreg_subkey_t *key; 4938670SJose.Borrego@Sun.COM char *entry; 4948670SJose.Borrego@Sun.COM char *p; 4958670SJose.Borrego@Sun.COM int subkeylen; 4968670SJose.Borrego@Sun.COM int count = 0; 4978474SJose.Borrego@Sun.COM 4988474SJose.Borrego@Sun.COM if (subkey == NULL) 4998474SJose.Borrego@Sun.COM return (NULL); 5008474SJose.Borrego@Sun.COM 5018474SJose.Borrego@Sun.COM if (list_is_empty(&winreg_keylist.kl_list)) 5028474SJose.Borrego@Sun.COM return (NULL); 5038474SJose.Borrego@Sun.COM 5048670SJose.Borrego@Sun.COM subkeylen = strlen(subkey); 5058670SJose.Borrego@Sun.COM 5068670SJose.Borrego@Sun.COM for (key = list_head(&winreg_keylist.kl_list); 5078670SJose.Borrego@Sun.COM key != NULL; key = list_next(&winreg_keylist.kl_list, key)) { 5088670SJose.Borrego@Sun.COM if (strncasecmp(subkey, key->sk_name, subkeylen) == 0) { 5098670SJose.Borrego@Sun.COM p = key->sk_name + subkeylen; 5108670SJose.Borrego@Sun.COM 5118670SJose.Borrego@Sun.COM if ((*p != '\\') || (*p == '\0')) { 5128670SJose.Borrego@Sun.COM /* 5138670SJose.Borrego@Sun.COM * Not the same subkey or an exact match. 5148670SJose.Borrego@Sun.COM * We're looking for children of subkey. 5158670SJose.Borrego@Sun.COM */ 5168670SJose.Borrego@Sun.COM continue; 5178670SJose.Borrego@Sun.COM } 5188670SJose.Borrego@Sun.COM 5198670SJose.Borrego@Sun.COM ++p; 5208670SJose.Borrego@Sun.COM 5218670SJose.Borrego@Sun.COM if (count < index) { 5228670SJose.Borrego@Sun.COM ++count; 5238670SJose.Borrego@Sun.COM continue; 5248670SJose.Borrego@Sun.COM } 5258670SJose.Borrego@Sun.COM 5268670SJose.Borrego@Sun.COM if ((entry = NDR_STRDUP(mxa, p)) == NULL) 5278670SJose.Borrego@Sun.COM return (NULL); 5288670SJose.Borrego@Sun.COM 5298670SJose.Borrego@Sun.COM if ((p = strchr(entry, '\\')) != NULL) 5308670SJose.Borrego@Sun.COM *p = '\0'; 5318670SJose.Borrego@Sun.COM 5328670SJose.Borrego@Sun.COM return (entry); 5338474SJose.Borrego@Sun.COM } 5348670SJose.Borrego@Sun.COM } 5358474SJose.Borrego@Sun.COM 5368474SJose.Borrego@Sun.COM return (NULL); 5378474SJose.Borrego@Sun.COM } 5388474SJose.Borrego@Sun.COM 5398474SJose.Borrego@Sun.COM /* 5408474SJose.Borrego@Sun.COM * winreg_s_DeleteValue 5418474SJose.Borrego@Sun.COM */ 5428474SJose.Borrego@Sun.COM /*ARGSUSED*/ 5438474SJose.Borrego@Sun.COM static int 5448474SJose.Borrego@Sun.COM winreg_s_DeleteValue(void *arg, ndr_xa_t *mxa) 5458474SJose.Borrego@Sun.COM { 5468474SJose.Borrego@Sun.COM struct winreg_DeleteValue *param = arg; 5478474SJose.Borrego@Sun.COM 5488474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 5498474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 5508474SJose.Borrego@Sun.COM } 5518474SJose.Borrego@Sun.COM 5528474SJose.Borrego@Sun.COM /* 5538474SJose.Borrego@Sun.COM * winreg_s_EnumKey 5548474SJose.Borrego@Sun.COM */ 5558474SJose.Borrego@Sun.COM static int 5568474SJose.Borrego@Sun.COM winreg_s_EnumKey(void *arg, ndr_xa_t *mxa) 5578474SJose.Borrego@Sun.COM { 5588474SJose.Borrego@Sun.COM struct winreg_EnumKey *param = arg; 5598474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 5608670SJose.Borrego@Sun.COM ndr_handle_t *hd; 5618670SJose.Borrego@Sun.COM char *subkey; 5628670SJose.Borrego@Sun.COM char *name = NULL; 5638474SJose.Borrego@Sun.COM 5648670SJose.Borrego@Sun.COM if ((hd = ndr_hdlookup(mxa, id)) != NULL) 5658670SJose.Borrego@Sun.COM name = hd->nh_data; 5668474SJose.Borrego@Sun.COM 5678670SJose.Borrego@Sun.COM if (hd == NULL || name == NULL) { 5688474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_EnumKey)); 5698474SJose.Borrego@Sun.COM param->status = ERROR_NO_MORE_ITEMS; 5708474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 5718474SJose.Borrego@Sun.COM } 5728474SJose.Borrego@Sun.COM 5738670SJose.Borrego@Sun.COM subkey = winreg_enum_subkey(mxa, name, param->index); 5748670SJose.Borrego@Sun.COM if (subkey == NULL) { 5758474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_EnumKey)); 5768670SJose.Borrego@Sun.COM param->status = ERROR_NO_MORE_ITEMS; 5778474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 5788474SJose.Borrego@Sun.COM } 5798474SJose.Borrego@Sun.COM 5808670SJose.Borrego@Sun.COM if (NDR_MSTRING(mxa, subkey, (ndr_mstring_t *)¶m->name_out) == -1) { 5818474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_EnumKey)); 5828474SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 5838474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 5848474SJose.Borrego@Sun.COM } 5858670SJose.Borrego@Sun.COM /* 5868670SJose.Borrego@Sun.COM * This request requires that the length includes the null. 5878670SJose.Borrego@Sun.COM */ 5888670SJose.Borrego@Sun.COM param->name_out.length = param->name_out.allosize; 5898474SJose.Borrego@Sun.COM 5908474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 5918474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 5928474SJose.Borrego@Sun.COM } 5938474SJose.Borrego@Sun.COM 5948474SJose.Borrego@Sun.COM /* 5958474SJose.Borrego@Sun.COM * winreg_s_EnumValue 5968474SJose.Borrego@Sun.COM */ 5978474SJose.Borrego@Sun.COM static int 5988474SJose.Borrego@Sun.COM winreg_s_EnumValue(void *arg, ndr_xa_t *mxa) 5998474SJose.Borrego@Sun.COM { 6008474SJose.Borrego@Sun.COM struct winreg_EnumValue *param = arg; 6018474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 6028474SJose.Borrego@Sun.COM 6038474SJose.Borrego@Sun.COM if (ndr_hdlookup(mxa, id) == NULL) { 6048474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_EnumValue)); 6058474SJose.Borrego@Sun.COM param->status = ERROR_NO_MORE_ITEMS; 6068474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 6078474SJose.Borrego@Sun.COM } 6088474SJose.Borrego@Sun.COM 6098474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_EnumValue)); 6108474SJose.Borrego@Sun.COM param->status = ERROR_NO_MORE_ITEMS; 6118474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 6128474SJose.Borrego@Sun.COM } 6138474SJose.Borrego@Sun.COM 6148474SJose.Borrego@Sun.COM /* 6158474SJose.Borrego@Sun.COM * winreg_s_FlushKey 6168474SJose.Borrego@Sun.COM * 6178474SJose.Borrego@Sun.COM * Flush the attributes associated with the specified open key to disk. 6188474SJose.Borrego@Sun.COM */ 6198474SJose.Borrego@Sun.COM static int 6208474SJose.Borrego@Sun.COM winreg_s_FlushKey(void *arg, ndr_xa_t *mxa) 6218474SJose.Borrego@Sun.COM { 6228474SJose.Borrego@Sun.COM struct winreg_FlushKey *param = arg; 6238474SJose.Borrego@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 6248474SJose.Borrego@Sun.COM 6258474SJose.Borrego@Sun.COM if (ndr_hdlookup(mxa, id) == NULL) 6268474SJose.Borrego@Sun.COM param->status = ERROR_INVALID_HANDLE; 6278474SJose.Borrego@Sun.COM else 6288474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 6298474SJose.Borrego@Sun.COM 6308474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 6318474SJose.Borrego@Sun.COM } 6328474SJose.Borrego@Sun.COM 6338474SJose.Borrego@Sun.COM /* 6348474SJose.Borrego@Sun.COM * winreg_s_GetKeySec 6358474SJose.Borrego@Sun.COM */ 6368474SJose.Borrego@Sun.COM /*ARGSUSED*/ 6378474SJose.Borrego@Sun.COM static int 6388474SJose.Borrego@Sun.COM winreg_s_GetKeySec(void *arg, ndr_xa_t *mxa) 6398474SJose.Borrego@Sun.COM { 6408474SJose.Borrego@Sun.COM struct winreg_GetKeySec *param = arg; 6418474SJose.Borrego@Sun.COM 6428474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_GetKeySec)); 6438474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 6448474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 6458474SJose.Borrego@Sun.COM } 6468474SJose.Borrego@Sun.COM 6478474SJose.Borrego@Sun.COM /* 6488474SJose.Borrego@Sun.COM * winreg_s_NotifyChange 6498474SJose.Borrego@Sun.COM */ 6508474SJose.Borrego@Sun.COM static int 6518474SJose.Borrego@Sun.COM winreg_s_NotifyChange(void *arg, ndr_xa_t *mxa) 6528474SJose.Borrego@Sun.COM { 6538474SJose.Borrego@Sun.COM struct winreg_NotifyChange *param = arg; 6548474SJose.Borrego@Sun.COM 6558474SJose.Borrego@Sun.COM if (ndr_is_admin(mxa)) 6568474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 6578474SJose.Borrego@Sun.COM else 6588474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 6598474SJose.Borrego@Sun.COM 6608474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 6618474SJose.Borrego@Sun.COM } 6628474SJose.Borrego@Sun.COM 6638474SJose.Borrego@Sun.COM /* 6648474SJose.Borrego@Sun.COM * winreg_s_OpenKey 6658474SJose.Borrego@Sun.COM * 6668474SJose.Borrego@Sun.COM * This is a request to open a windows registry key. 6678474SJose.Borrego@Sun.COM * If we recognize the key, we return a handle. 6688474SJose.Borrego@Sun.COM * 6698474SJose.Borrego@Sun.COM * Returns: 6708474SJose.Borrego@Sun.COM * ERROR_SUCCESS Valid handle returned. 6718474SJose.Borrego@Sun.COM * ERROR_FILE_NOT_FOUND No key or unable to allocate a handle. 6728474SJose.Borrego@Sun.COM */ 6738474SJose.Borrego@Sun.COM static int 6748474SJose.Borrego@Sun.COM winreg_s_OpenKey(void *arg, ndr_xa_t *mxa) 6758474SJose.Borrego@Sun.COM { 6768474SJose.Borrego@Sun.COM struct winreg_OpenKey *param = arg; 6779914Samw@Sun.COM ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 6789914Samw@Sun.COM ndr_handle_t *hd; 6798474SJose.Borrego@Sun.COM char *subkey = (char *)param->name.str; 6808474SJose.Borrego@Sun.COM winreg_subkey_t *key; 6818670SJose.Borrego@Sun.COM char *dupkey; 6828474SJose.Borrego@Sun.COM 6839914Samw@Sun.COM if (subkey == NULL || *subkey == '\0') { 6849914Samw@Sun.COM if ((hd = ndr_hdlookup(mxa, id)) != NULL) 6859914Samw@Sun.COM subkey = hd->nh_data; 6869914Samw@Sun.COM } 6879914Samw@Sun.COM 6889914Samw@Sun.COM id = NULL; 6899914Samw@Sun.COM 6908670SJose.Borrego@Sun.COM if (subkey == NULL || list_is_empty(&winreg_keylist.kl_list)) { 6918474SJose.Borrego@Sun.COM bzero(¶m->result_handle, sizeof (winreg_handle_t)); 6928474SJose.Borrego@Sun.COM param->status = ERROR_FILE_NOT_FOUND; 6938474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 6948474SJose.Borrego@Sun.COM } 6958474SJose.Borrego@Sun.COM 6968474SJose.Borrego@Sun.COM key = list_head(&winreg_keylist.kl_list); 6978474SJose.Borrego@Sun.COM do { 6988474SJose.Borrego@Sun.COM if (strcasecmp(subkey, key->sk_name) == 0) { 6998670SJose.Borrego@Sun.COM if (key->sk_predefined == B_TRUE) { 7008670SJose.Borrego@Sun.COM if ((dupkey = strdup(subkey)) == NULL) 7018670SJose.Borrego@Sun.COM break; 7028670SJose.Borrego@Sun.COM 7038670SJose.Borrego@Sun.COM id = ndr_hdalloc(mxa, dupkey); 7048670SJose.Borrego@Sun.COM if (id == NULL) 7058670SJose.Borrego@Sun.COM free(dupkey); 7068670SJose.Borrego@Sun.COM } else { 7078474SJose.Borrego@Sun.COM id = &key->sk_handle; 7088670SJose.Borrego@Sun.COM } 7098474SJose.Borrego@Sun.COM 7108474SJose.Borrego@Sun.COM if (id == NULL) 7118474SJose.Borrego@Sun.COM break; 7128474SJose.Borrego@Sun.COM 7138474SJose.Borrego@Sun.COM bcopy(id, ¶m->result_handle, 7148474SJose.Borrego@Sun.COM sizeof (winreg_handle_t)); 7158474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 7168474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 7178474SJose.Borrego@Sun.COM } 7188474SJose.Borrego@Sun.COM } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL); 7198474SJose.Borrego@Sun.COM 7208474SJose.Borrego@Sun.COM bzero(¶m->result_handle, sizeof (winreg_handle_t)); 7218474SJose.Borrego@Sun.COM param->status = ERROR_FILE_NOT_FOUND; 7228474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 7238474SJose.Borrego@Sun.COM } 7248474SJose.Borrego@Sun.COM 7258474SJose.Borrego@Sun.COM /* 7268474SJose.Borrego@Sun.COM * winreg_s_QueryKey 7278474SJose.Borrego@Sun.COM */ 7288474SJose.Borrego@Sun.COM /*ARGSUSED*/ 7298474SJose.Borrego@Sun.COM static int 7308474SJose.Borrego@Sun.COM winreg_s_QueryKey(void *arg, ndr_xa_t *mxa) 7318474SJose.Borrego@Sun.COM { 7328474SJose.Borrego@Sun.COM struct winreg_QueryKey *param = arg; 7338474SJose.Borrego@Sun.COM int rc; 7348474SJose.Borrego@Sun.COM winreg_string_t *name; 7358474SJose.Borrego@Sun.COM 7368474SJose.Borrego@Sun.COM name = (winreg_string_t *)¶m->name; 7378474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_QueryKey)); 7388474SJose.Borrego@Sun.COM if ((name = NDR_NEW(mxa, winreg_string_t)) != NULL) 7398474SJose.Borrego@Sun.COM rc = NDR_MSTRING(mxa, "", (ndr_mstring_t *)name); 7408474SJose.Borrego@Sun.COM 7418474SJose.Borrego@Sun.COM if ((name == NULL) || (rc != 0)) { 7428474SJose.Borrego@Sun.COM bzero(param, sizeof (struct winreg_QueryKey)); 7438474SJose.Borrego@Sun.COM param->status = ERROR_NOT_ENOUGH_MEMORY; 7448474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 7458474SJose.Borrego@Sun.COM } 7468474SJose.Borrego@Sun.COM 7478474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 7488474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 7498474SJose.Borrego@Sun.COM } 7508474SJose.Borrego@Sun.COM 7518474SJose.Borrego@Sun.COM /* 7528474SJose.Borrego@Sun.COM * winreg_s_QueryValue 7538474SJose.Borrego@Sun.COM * 7548474SJose.Borrego@Sun.COM * This is a request to get the value associated with a specified name. 7558474SJose.Borrego@Sun.COM * 7568474SJose.Borrego@Sun.COM * Returns: 7578474SJose.Borrego@Sun.COM * ERROR_SUCCESS Value returned. 7588474SJose.Borrego@Sun.COM * ERROR_FILE_NOT_FOUND PrimaryModule is not supported. 7598474SJose.Borrego@Sun.COM * ERROR_CANTREAD No such name or memory problem. 7608474SJose.Borrego@Sun.COM */ 7618474SJose.Borrego@Sun.COM static int 7628474SJose.Borrego@Sun.COM winreg_s_QueryValue(void *arg, ndr_xa_t *mxa) 7638474SJose.Borrego@Sun.COM { 7648474SJose.Borrego@Sun.COM struct winreg_QueryValue *param = arg; 7658474SJose.Borrego@Sun.COM struct winreg_value *pv; 7668474SJose.Borrego@Sun.COM char *name; 7678474SJose.Borrego@Sun.COM char *value; 7688474SJose.Borrego@Sun.COM DWORD slen; 7698474SJose.Borrego@Sun.COM DWORD msize; 7708474SJose.Borrego@Sun.COM 7718474SJose.Borrego@Sun.COM name = (char *)param->value_name.str; 7728474SJose.Borrego@Sun.COM 7738474SJose.Borrego@Sun.COM if (strcasecmp(name, "PrimaryModule") == 0) { 7748474SJose.Borrego@Sun.COM param->status = ERROR_FILE_NOT_FOUND; 7758474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 7768474SJose.Borrego@Sun.COM } 7778474SJose.Borrego@Sun.COM 7788474SJose.Borrego@Sun.COM if ((value = winreg_lookup_value(name)) == NULL) { 7798474SJose.Borrego@Sun.COM param->status = ERROR_CANTREAD; 7808474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 7818474SJose.Borrego@Sun.COM } 7828474SJose.Borrego@Sun.COM 783*10966SJordan.Brown@Sun.COM slen = smb_wcequiv_strlen(value) + sizeof (smb_wchar_t); 7848474SJose.Borrego@Sun.COM msize = sizeof (struct winreg_value) + slen; 7858474SJose.Borrego@Sun.COM 7868474SJose.Borrego@Sun.COM param->value = (struct winreg_value *)NDR_MALLOC(mxa, msize); 7878474SJose.Borrego@Sun.COM param->type = NDR_NEW(mxa, DWORD); 7888474SJose.Borrego@Sun.COM param->value_size = NDR_NEW(mxa, DWORD); 7898474SJose.Borrego@Sun.COM param->value_size_total = NDR_NEW(mxa, DWORD); 7908474SJose.Borrego@Sun.COM 7918474SJose.Borrego@Sun.COM if (param->value == NULL || param->type == NULL || 7928474SJose.Borrego@Sun.COM param->value_size == NULL || param->value_size_total == NULL) { 7938474SJose.Borrego@Sun.COM param->status = ERROR_CANTREAD; 7948474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 7958474SJose.Borrego@Sun.COM } 7968474SJose.Borrego@Sun.COM 7978474SJose.Borrego@Sun.COM bzero(param->value, msize); 7988474SJose.Borrego@Sun.COM pv = param->value; 7998474SJose.Borrego@Sun.COM pv->vc_first_is = 0; 8008474SJose.Borrego@Sun.COM pv->vc_length_is = slen; 8018474SJose.Borrego@Sun.COM /*LINTED E_BAD_PTR_CAST_ALIGN*/ 802*10966SJordan.Brown@Sun.COM (void) ndr_mbstowcs(NULL, (smb_wchar_t *)pv->value, value, slen); 8038474SJose.Borrego@Sun.COM 8048474SJose.Borrego@Sun.COM *param->type = 1; 8058474SJose.Borrego@Sun.COM *param->value_size = slen; 8068474SJose.Borrego@Sun.COM *param->value_size_total = slen; 8078474SJose.Borrego@Sun.COM 8088474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 8098474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 8108474SJose.Borrego@Sun.COM } 8118474SJose.Borrego@Sun.COM 8128474SJose.Borrego@Sun.COM /* 8138474SJose.Borrego@Sun.COM * Lookup a name in the registry and return the associated value. 8148474SJose.Borrego@Sun.COM * Our registry is a case-insensitive, name-value pair table. 8158474SJose.Borrego@Sun.COM * 8168474SJose.Borrego@Sun.COM * Windows ProductType: WinNT, ServerNT, LanmanNT. 8178474SJose.Borrego@Sun.COM * Windows NT4.0 workstation: WinNT 8188474SJose.Borrego@Sun.COM * Windows NT4.0 server: ServerNT 8198474SJose.Borrego@Sun.COM * 8208474SJose.Borrego@Sun.COM * If LanmanNT is used here, Windows 2000 sends LsarQueryInfoPolicy 8218474SJose.Borrego@Sun.COM * with info level 6, which we don't support. If we use ServerNT 8228474SJose.Borrego@Sun.COM * (as reported by NT4.0 Server) Windows 2000 send requests for 8238474SJose.Borrego@Sun.COM * levels 3 and 5, which are support. 8248474SJose.Borrego@Sun.COM * 8258474SJose.Borrego@Sun.COM * On success, returns a pointer to the value. Otherwise returns 8268474SJose.Borrego@Sun.COM * a null pointer. 8278474SJose.Borrego@Sun.COM */ 8288474SJose.Borrego@Sun.COM static char * 8298474SJose.Borrego@Sun.COM winreg_lookup_value(const char *name) 8308474SJose.Borrego@Sun.COM { 8318474SJose.Borrego@Sun.COM static struct registry { 8328474SJose.Borrego@Sun.COM char *name; 8338474SJose.Borrego@Sun.COM char *value; 8348474SJose.Borrego@Sun.COM } registry[] = { 83510504SKeyur.Desai@Sun.COM { "CurrentVersion", "4.0" }, 8368474SJose.Borrego@Sun.COM { "ProductType", "ServerNT" }, 8378474SJose.Borrego@Sun.COM { "Sources", NULL } /* product name */ 8388474SJose.Borrego@Sun.COM }; 8398474SJose.Borrego@Sun.COM 8408474SJose.Borrego@Sun.COM int i; 8418474SJose.Borrego@Sun.COM 8428474SJose.Borrego@Sun.COM for (i = 0; i < sizeof (registry)/sizeof (registry[0]); ++i) { 8438474SJose.Borrego@Sun.COM if (strcasecmp(registry[i].name, name) == 0) { 8448474SJose.Borrego@Sun.COM if (registry[i].value == NULL) 8458474SJose.Borrego@Sun.COM return (winreg_sysname); 8468474SJose.Borrego@Sun.COM else 8478474SJose.Borrego@Sun.COM return (registry[i].value); 8488474SJose.Borrego@Sun.COM } 8498474SJose.Borrego@Sun.COM } 8508474SJose.Borrego@Sun.COM 8518474SJose.Borrego@Sun.COM return (NULL); 8528474SJose.Borrego@Sun.COM } 8538474SJose.Borrego@Sun.COM 8548474SJose.Borrego@Sun.COM /* 8558474SJose.Borrego@Sun.COM * winreg_s_SetKeySec 8568474SJose.Borrego@Sun.COM */ 8578474SJose.Borrego@Sun.COM /*ARGSUSED*/ 8588474SJose.Borrego@Sun.COM static int 8598474SJose.Borrego@Sun.COM winreg_s_SetKeySec(void *arg, ndr_xa_t *mxa) 8608474SJose.Borrego@Sun.COM { 8618474SJose.Borrego@Sun.COM struct winreg_SetKeySec *param = arg; 8628474SJose.Borrego@Sun.COM 8638474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 8648474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 8658474SJose.Borrego@Sun.COM } 8668474SJose.Borrego@Sun.COM 8678474SJose.Borrego@Sun.COM /* 8688474SJose.Borrego@Sun.COM * winreg_s_CreateValue 8698474SJose.Borrego@Sun.COM */ 8708474SJose.Borrego@Sun.COM /*ARGSUSED*/ 8718474SJose.Borrego@Sun.COM static int 8728474SJose.Borrego@Sun.COM winreg_s_CreateValue(void *arg, ndr_xa_t *mxa) 8738474SJose.Borrego@Sun.COM { 8748474SJose.Borrego@Sun.COM struct winreg_CreateValue *param = arg; 8758474SJose.Borrego@Sun.COM 8768474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 8778474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 8788474SJose.Borrego@Sun.COM } 8798474SJose.Borrego@Sun.COM 8808474SJose.Borrego@Sun.COM /* 8818474SJose.Borrego@Sun.COM * winreg_s_Shutdown 8828474SJose.Borrego@Sun.COM * 8838474SJose.Borrego@Sun.COM * Attempt to shutdown or reboot the system: access denied. 8848474SJose.Borrego@Sun.COM */ 8858474SJose.Borrego@Sun.COM /*ARGSUSED*/ 8868474SJose.Borrego@Sun.COM static int 8878474SJose.Borrego@Sun.COM winreg_s_Shutdown(void *arg, ndr_xa_t *mxa) 8888474SJose.Borrego@Sun.COM { 8898474SJose.Borrego@Sun.COM struct winreg_Shutdown *param = arg; 8908474SJose.Borrego@Sun.COM 8918474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 8928474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 8938474SJose.Borrego@Sun.COM } 8948474SJose.Borrego@Sun.COM 8958474SJose.Borrego@Sun.COM /* 8968474SJose.Borrego@Sun.COM * winreg_s_AbortShutdown 8978474SJose.Borrego@Sun.COM * 8988474SJose.Borrego@Sun.COM * Abort a shutdown request. 8998474SJose.Borrego@Sun.COM */ 9008474SJose.Borrego@Sun.COM static int 9018474SJose.Borrego@Sun.COM winreg_s_AbortShutdown(void *arg, ndr_xa_t *mxa) 9028474SJose.Borrego@Sun.COM { 9038474SJose.Borrego@Sun.COM struct winreg_AbortShutdown *param = arg; 9048474SJose.Borrego@Sun.COM 9058474SJose.Borrego@Sun.COM if (ndr_is_admin(mxa)) 9068474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 9078474SJose.Borrego@Sun.COM else 9088474SJose.Borrego@Sun.COM param->status = ERROR_ACCESS_DENIED; 9098474SJose.Borrego@Sun.COM 9108474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 9118474SJose.Borrego@Sun.COM } 9128474SJose.Borrego@Sun.COM 9138474SJose.Borrego@Sun.COM /* 9148474SJose.Borrego@Sun.COM * winreg_s_GetVersion 9158474SJose.Borrego@Sun.COM * 9168474SJose.Borrego@Sun.COM * Return the windows registry version. The current version is 5. 9178474SJose.Borrego@Sun.COM * This call is usually made prior to enumerating or querying registry 9188474SJose.Borrego@Sun.COM * keys or values. 9198474SJose.Borrego@Sun.COM */ 9208474SJose.Borrego@Sun.COM /*ARGSUSED*/ 9218474SJose.Borrego@Sun.COM static int 9228474SJose.Borrego@Sun.COM winreg_s_GetVersion(void *arg, ndr_xa_t *mxa) 9238474SJose.Borrego@Sun.COM { 9248474SJose.Borrego@Sun.COM struct winreg_GetVersion *param = arg; 9258474SJose.Borrego@Sun.COM 9268474SJose.Borrego@Sun.COM param->version = 5; 9278474SJose.Borrego@Sun.COM param->status = ERROR_SUCCESS; 9288474SJose.Borrego@Sun.COM return (NDR_DRC_OK); 9298474SJose.Borrego@Sun.COM } 930