static WCHAR *decode_url( LPCWSTR url, DWORD *len ) { const WCHAR *p = url; WCHAR hex[3], *q, *ret; if (!(ret = heap_alloc( *len * sizeof(WCHAR) ))) return NULL; q = ret; while (*len > 0) { if (p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] )) { hex[0] = p[1]; hex[1] = p[2]; hex[2] = 0; *q++ = strtolW( hex, NULL, 16 ); p += 3; *len -= 3; } else { *q++ = *p++; *len -= 1; } } *len = q - ret; return ret; }
static WCHAR *url_decode( WCHAR *str, ULONG len, WS_HEAP *heap, ULONG *ret_len ) { WCHAR *p = str, *q, *ret; BOOL decode = FALSE, convert = FALSE; ULONG i, len_utf8, len_left; unsigned char *utf8, *r; *ret_len = len; for (i = 0; i < len; i++, p++) { if ((len - i) < 3) break; if (p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] )) { decode = TRUE; if (url_decode_byte( p[1], p[2] ) > 159) { convert = TRUE; break; } *ret_len -= 2; } } if (!decode) return str; if (!convert) { if (!(q = ret = ws_alloc( heap, *ret_len * sizeof(WCHAR) ))) return NULL; p = str; while (len) { if (len >= 3 && p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] )) { *q++ = url_decode_byte( p[1], p[2] ); p += 3; len -= 3; } else { *q++ = *p++; len -= 1; } } return ret; } if (!(r = utf8 = strdup_utf8( str, len, &len_utf8 ))) return NULL; len_left = len_utf8; while (len_left) { if (len_left >= 3 && r[0] == '%' && isxdigit( r[1] ) && isxdigit( r[2] )) { r[0] = url_decode_byte( r[1], r[2] ); len_left -= 3; memmove( r + 1, r + 3, len_left ); len_utf8 -= 2; } else len_left -= 1; r++; } if (!(*ret_len = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, (char *)utf8, len_utf8, NULL, 0 ))) { WARN( "invalid UTF-8 sequence\n" ); heap_free( utf8 ); return NULL; } if ((ret = ws_alloc( heap, *ret_len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_UTF8, 0, (char *)utf8, len_utf8, ret, *ret_len ); heap_free( utf8 ); return ret; }
static HRESULT do_process_key(LPCOLESTR *pstr, HKEY parent_key, strbuf *buf, BOOL do_register) { LPCOLESTR iter; HRESULT hres; LONG lres; HKEY hkey = 0; strbuf name; enum { NORMAL, NO_REMOVE, IS_VAL, FORCE_REMOVE, DO_DELETE } key_type = NORMAL; static const WCHAR wstrNoRemove[] = {'N','o','R','e','m','o','v','e',0}; static const WCHAR wstrForceRemove[] = {'F','o','r','c','e','R','e','m','o','v','e',0}; static const WCHAR wstrDelete[] = {'D','e','l','e','t','e',0}; static const WCHAR wstrval[] = {'v','a','l',0}; iter = *pstr; hres = get_word(&iter, buf); if(FAILED(hres)) return hres; strbuf_init(&name); while(buf->str[1] || buf->str[0] != '}') { key_type = NORMAL; if(!lstrcmpiW(buf->str, wstrNoRemove)) key_type = NO_REMOVE; else if(!lstrcmpiW(buf->str, wstrForceRemove)) key_type = FORCE_REMOVE; else if(!lstrcmpiW(buf->str, wstrval)) key_type = IS_VAL; else if(!lstrcmpiW(buf->str, wstrDelete)) key_type = DO_DELETE; if(key_type != NORMAL) { hres = get_word(&iter, buf); if(FAILED(hres)) break; } TRACE("name = %s\n", debugstr_w(buf->str)); if(do_register) { if(key_type == IS_VAL) { hkey = parent_key; strbuf_write(buf->str, &name, -1); }else if(key_type == DO_DELETE) { TRACE("Deleting %s\n", debugstr_w(buf->str)); RegDeleteTreeW(parent_key, buf->str); }else { if(key_type == FORCE_REMOVE) RegDeleteTreeW(parent_key, buf->str); lres = RegCreateKeyW(parent_key, buf->str, &hkey); if(lres != ERROR_SUCCESS) { WARN("Could not create(open) key: %08x\n", lres); hres = HRESULT_FROM_WIN32(lres); break; } } }else if(key_type != IS_VAL && key_type != DO_DELETE) { strbuf_write(buf->str, &name, -1); lres = RegOpenKeyW(parent_key, buf->str, &hkey); if(lres != ERROR_SUCCESS) WARN("Could not open key %s: %08x\n", debugstr_w(name.str), lres); } if(key_type != DO_DELETE && *iter == '=') { iter++; hres = get_word(&iter, buf); if(FAILED(hres)) break; if(buf->len != 1) { WARN("Wrong registry type: %s\n", debugstr_w(buf->str)); hres = DISP_E_EXCEPTION; break; } if(do_register) { switch(buf->str[0]) { case 's': hres = get_word(&iter, buf); if(FAILED(hres)) break; lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_SZ, (PBYTE)buf->str, (lstrlenW(buf->str)+1)*sizeof(WCHAR)); if(lres != ERROR_SUCCESS) { WARN("Could set value of key: %08x\n", lres); hres = HRESULT_FROM_WIN32(lres); break; } break; case 'd': { DWORD dw; hres = get_word(&iter, buf); if(FAILED(hres)) break; dw = atoiW(buf->str); lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_DWORD, (PBYTE)&dw, sizeof(dw)); if(lres != ERROR_SUCCESS) { WARN("Could set value of key: %08x\n", lres); hres = HRESULT_FROM_WIN32(lres); break; } break; } case 'b': { BYTE *bytes; DWORD count; DWORD i; hres = get_word(&iter, buf); if(FAILED(hres)) break; count = (lstrlenW(buf->str) + 1) / 2; bytes = HeapAlloc(GetProcessHeap(), 0, count); if(bytes == NULL) { hres = E_OUTOFMEMORY; break; } for(i = 0; i < count && buf->str[2*i]; i++) { WCHAR digits[3]; if(!isxdigitW(buf->str[2*i]) || !isxdigitW(buf->str[2*i + 1])) { hres = E_FAIL; break; } digits[0] = buf->str[2*i]; digits[1] = buf->str[2*i + 1]; digits[2] = 0; bytes[i] = (BYTE) strtoulW(digits, NULL, 16); } if(SUCCEEDED(hres)) { lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_BINARY, bytes, count); if(lres != ERROR_SUCCESS) { WARN("Could not set value of key: 0x%08x\n", lres); hres = HRESULT_FROM_WIN32(lres); } } HeapFree(GetProcessHeap(), 0, bytes); break; } default: WARN("Wrong resource type: %s\n", debugstr_w(buf->str)); hres = DISP_E_EXCEPTION; }; if(FAILED(hres)) break; }else { if(*iter == '-') iter++; hres = get_word(&iter, buf); if(FAILED(hres)) break; } }else if(key_type == IS_VAL) { WARN("value not set!\n"); hres = DISP_E_EXCEPTION; break; } if(key_type != IS_VAL && key_type != DO_DELETE && *iter == '{' && isspaceW(iter[1])) { hres = get_word(&iter, buf); if(FAILED(hres)) break; hres = do_process_key(&iter, hkey, buf, do_register); if(FAILED(hres)) break; } TRACE("%x %x\n", do_register, key_type); if(!do_register && (key_type == NORMAL || key_type == FORCE_REMOVE)) { TRACE("Deleting %s\n", debugstr_w(name.str)); RegDeleteKeyW(parent_key, name.str); } if(hkey && key_type != IS_VAL) RegCloseKey(hkey); hkey = 0; name.len = 0; hres = get_word(&iter, buf); if(FAILED(hres)) break; } HeapFree(GetProcessHeap(), 0, name.str); if(hkey && key_type != IS_VAL) RegCloseKey(hkey); *pstr = iter; return hres; }
/********************************************************************* * iswxdigit (NTDLL.@) * * Checks if a unicode char wc is an extended digit * * RETURNS * TRUE: The unicode char wc is an extended digit. * FALSE: Otherwise */ INT __cdecl NTDLL_iswxdigit( WCHAR wc ) { return isxdigitW(wc); }