1 /* 2 * Copyright 2005 Jacek Caban 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include <precomp.h> 20 21 22 /************************************************************** 23 * ATLRegistrar implementation 24 */ 25 26 static const struct { 27 WCHAR name[22]; 28 HKEY key; 29 } root_keys[] = { 30 {{'H','K','E','Y','_','C','L','A','S','S','E','S','_','R','O','O','T',0}, 31 HKEY_CLASSES_ROOT}, 32 {{'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R',0}, 33 HKEY_CURRENT_USER}, 34 {{'H','K','E','Y','_','L','O','C','A','L','_','M','A','C','H','I','N','E',0}, 35 HKEY_LOCAL_MACHINE}, 36 {{'H','K','E','Y','_','U','S','E','R','S',0}, 37 HKEY_USERS}, 38 {{'H','K','E','Y','_','P','E','R','F','O','R','M','A','N','C','E','_','D','A','T','A',0}, 39 HKEY_PERFORMANCE_DATA}, 40 {{'H','K','E','Y','_','D','Y','N','_','D','A','T','A',0}, 41 HKEY_DYN_DATA}, 42 {{'H','K','E','Y','_','C','U','R','R','E','N','T','_','C','O','N','F','I','G',0}, 43 HKEY_CURRENT_CONFIG}, 44 {{'H','K','C','R',0}, HKEY_CLASSES_ROOT}, 45 {{'H','K','C','U',0}, HKEY_CURRENT_USER}, 46 {{'H','K','L','M',0}, HKEY_LOCAL_MACHINE}, 47 {{'H','K','U',0}, HKEY_USERS}, 48 {{'H','K','P','D',0}, HKEY_PERFORMANCE_DATA}, 49 {{'H','K','D','D',0}, HKEY_DYN_DATA}, 50 {{'H','K','C','C',0}, HKEY_CURRENT_CONFIG} 51 }; 52 53 typedef struct rep_list_str { 54 LPOLESTR key; 55 LPOLESTR item; 56 int key_len; 57 struct rep_list_str *next; 58 } rep_list; 59 60 typedef struct { 61 IRegistrar IRegistrar_iface; 62 LONG ref; 63 rep_list *rep; 64 } Registrar; 65 66 typedef struct { 67 LPOLESTR str; 68 DWORD alloc; 69 DWORD len; 70 } strbuf; 71 72 static inline Registrar *impl_from_IRegistrar(IRegistrar *iface) 73 { 74 return CONTAINING_RECORD(iface, Registrar, IRegistrar_iface); 75 } 76 77 static void strbuf_init(strbuf *buf) 78 { 79 buf->str = HeapAlloc(GetProcessHeap(), 0, 128*sizeof(WCHAR)); 80 buf->alloc = 128; 81 buf->len = 0; 82 } 83 84 static void strbuf_write(LPCOLESTR str, strbuf *buf, int len) 85 { 86 if(len == -1) 87 len = lstrlenW(str); 88 if(buf->len+len+1 >= buf->alloc) { 89 buf->alloc = (buf->len+len)<<1; 90 buf->str = HeapReAlloc(GetProcessHeap(), 0, buf->str, buf->alloc*sizeof(WCHAR)); 91 } 92 memcpy(buf->str+buf->len, str, len*sizeof(OLECHAR)); 93 buf->len += len; 94 buf->str[buf->len] = '\0'; 95 } 96 97 static HRESULT get_word(LPCOLESTR *str, strbuf *buf) 98 { 99 LPCOLESTR iter, iter2 = *str; 100 101 buf->len = 0; 102 buf->str[0] = '\0'; 103 104 while(isspaceW(*iter2)) 105 iter2++; 106 iter = iter2; 107 if(!*iter) { 108 *str = iter; 109 return S_OK; 110 } 111 112 if(*iter == '}' || *iter == '=') { 113 strbuf_write(iter++, buf, 1); 114 }else if(*iter == '\'') { 115 iter2 = ++iter; 116 iter = strchrW(iter, '\''); 117 if(!iter) { 118 WARN("Unexpected end of script\n"); 119 *str = iter; 120 return DISP_E_EXCEPTION; 121 } 122 strbuf_write(iter2, buf, iter-iter2); 123 iter++; 124 }else { 125 while(*iter && !isspaceW(*iter)) 126 iter++; 127 strbuf_write(iter2, buf, iter-iter2); 128 } 129 130 while(isspaceW(*iter)) 131 iter++; 132 *str = iter; 133 return S_OK; 134 } 135 136 static HRESULT do_preprocess(const Registrar *This, LPCOLESTR data, strbuf *buf) 137 { 138 LPCOLESTR iter, iter2 = data; 139 rep_list *rep_iter; 140 static const WCHAR wstr[] = {'%',0}; 141 142 iter = strchrW(data, '%'); 143 while(iter) { 144 strbuf_write(iter2, buf, iter-iter2); 145 146 iter2 = ++iter; 147 if(!*iter2) 148 return DISP_E_EXCEPTION; 149 iter = strchrW(iter2, '%'); 150 if(!iter) 151 return DISP_E_EXCEPTION; 152 153 if(iter == iter2) { 154 strbuf_write(wstr, buf, 1); 155 }else { 156 for(rep_iter = This->rep; rep_iter; rep_iter = rep_iter->next) { 157 if(rep_iter->key_len == iter-iter2 158 && !memicmpW(iter2, rep_iter->key, rep_iter->key_len)) 159 break; 160 } 161 if(!rep_iter) { 162 WARN("Could not find replacement: %s\n", debugstr_wn(iter2, iter-iter2)); 163 return DISP_E_EXCEPTION; 164 } 165 166 strbuf_write(rep_iter->item, buf, -1); 167 } 168 169 iter2 = ++iter; 170 iter = strchrW(iter, '%'); 171 } 172 173 strbuf_write(iter2, buf, -1); 174 TRACE("%s\n", debugstr_w(buf->str)); 175 176 return S_OK; 177 } 178 179 static HRESULT do_process_key(LPCOLESTR *pstr, HKEY parent_key, strbuf *buf, BOOL do_register) 180 { 181 LPCOLESTR iter; 182 HRESULT hres; 183 LONG lres; 184 HKEY hkey = 0; 185 strbuf name; 186 187 enum { 188 NORMAL, 189 NO_REMOVE, 190 IS_VAL, 191 FORCE_REMOVE, 192 DO_DELETE 193 } key_type = NORMAL; 194 195 static const WCHAR wstrNoRemove[] = {'N','o','R','e','m','o','v','e',0}; 196 static const WCHAR wstrForceRemove[] = {'F','o','r','c','e','R','e','m','o','v','e',0}; 197 static const WCHAR wstrDelete[] = {'D','e','l','e','t','e',0}; 198 static const WCHAR wstrval[] = {'v','a','l',0}; 199 200 iter = *pstr; 201 hres = get_word(&iter, buf); 202 if(FAILED(hres)) 203 return hres; 204 strbuf_init(&name); 205 206 while(buf->str[1] || buf->str[0] != '}') { 207 key_type = NORMAL; 208 if(!lstrcmpiW(buf->str, wstrNoRemove)) 209 key_type = NO_REMOVE; 210 else if(!lstrcmpiW(buf->str, wstrForceRemove)) 211 key_type = FORCE_REMOVE; 212 else if(!lstrcmpiW(buf->str, wstrval)) 213 key_type = IS_VAL; 214 else if(!lstrcmpiW(buf->str, wstrDelete)) 215 key_type = DO_DELETE; 216 217 if(key_type != NORMAL) { 218 hres = get_word(&iter, buf); 219 if(FAILED(hres)) 220 break; 221 } 222 TRACE("name = %s\n", debugstr_w(buf->str)); 223 224 if(do_register) { 225 if(key_type == IS_VAL) { 226 hkey = parent_key; 227 strbuf_write(buf->str, &name, -1); 228 }else if(key_type == DO_DELETE) { 229 TRACE("Deleting %s\n", debugstr_w(buf->str)); 230 RegDeleteTreeW(parent_key, buf->str); 231 }else { 232 if(key_type == FORCE_REMOVE) 233 RegDeleteTreeW(parent_key, buf->str); 234 lres = RegCreateKeyW(parent_key, buf->str, &hkey); 235 if(lres != ERROR_SUCCESS) { 236 WARN("Could not create(open) key: %08x\n", lres); 237 hres = HRESULT_FROM_WIN32(lres); 238 break; 239 } 240 } 241 }else if(key_type != IS_VAL && key_type != DO_DELETE) { 242 strbuf_write(buf->str, &name, -1); 243 lres = RegOpenKeyW(parent_key, buf->str, &hkey); 244 if(lres != ERROR_SUCCESS) 245 WARN("Could not open key %s: %08x\n", debugstr_w(name.str), lres); 246 } 247 248 if(key_type != DO_DELETE && *iter == '=') { 249 iter++; 250 hres = get_word(&iter, buf); 251 if(FAILED(hres)) 252 break; 253 if(buf->len != 1) { 254 WARN("Wrong registry type: %s\n", debugstr_w(buf->str)); 255 hres = DISP_E_EXCEPTION; 256 break; 257 } 258 if(do_register) { 259 switch(buf->str[0]) { 260 case 's': 261 hres = get_word(&iter, buf); 262 if(FAILED(hres)) 263 break; 264 lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_SZ, (PBYTE)buf->str, 265 (lstrlenW(buf->str)+1)*sizeof(WCHAR)); 266 if(lres != ERROR_SUCCESS) { 267 WARN("Could set value of key: %08x\n", lres); 268 hres = HRESULT_FROM_WIN32(lres); 269 break; 270 } 271 break; 272 case 'd': { 273 DWORD dw; 274 hres = get_word(&iter, buf); 275 if(FAILED(hres)) 276 break; 277 dw = atoiW(buf->str); 278 lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_DWORD, 279 (PBYTE)&dw, sizeof(dw)); 280 if(lres != ERROR_SUCCESS) { 281 WARN("Could set value of key: %08x\n", lres); 282 hres = HRESULT_FROM_WIN32(lres); 283 break; 284 } 285 break; 286 } 287 case 'b': { 288 BYTE *bytes; 289 DWORD count; 290 DWORD i; 291 hres = get_word(&iter, buf); 292 if(FAILED(hres)) 293 break; 294 count = (lstrlenW(buf->str) + 1) / 2; 295 bytes = HeapAlloc(GetProcessHeap(), 0, count); 296 if(bytes == NULL) { 297 hres = E_OUTOFMEMORY; 298 break; 299 } 300 for(i = 0; i < count && buf->str[2*i]; i++) { 301 WCHAR digits[3]; 302 if(!isxdigitW(buf->str[2*i]) || !isxdigitW(buf->str[2*i + 1])) { 303 hres = E_FAIL; 304 break; 305 } 306 digits[0] = buf->str[2*i]; 307 digits[1] = buf->str[2*i + 1]; 308 digits[2] = 0; 309 bytes[i] = (BYTE) strtoulW(digits, NULL, 16); 310 } 311 if(SUCCEEDED(hres)) { 312 lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_BINARY, 313 bytes, count); 314 if(lres != ERROR_SUCCESS) { 315 WARN("Could not set value of key: 0x%08x\n", lres); 316 hres = HRESULT_FROM_WIN32(lres); 317 } 318 } 319 HeapFree(GetProcessHeap(), 0, bytes); 320 break; 321 } 322 default: 323 WARN("Wrong resource type: %s\n", debugstr_w(buf->str)); 324 hres = DISP_E_EXCEPTION; 325 }; 326 if(FAILED(hres)) 327 break; 328 }else { 329 if(*iter == '-') 330 iter++; 331 hres = get_word(&iter, buf); 332 if(FAILED(hres)) 333 break; 334 } 335 }else if(key_type == IS_VAL) { 336 WARN("value not set!\n"); 337 hres = DISP_E_EXCEPTION; 338 break; 339 } 340 341 if(key_type != IS_VAL && key_type != DO_DELETE && *iter == '{' && isspaceW(iter[1])) { 342 hres = get_word(&iter, buf); 343 if(FAILED(hres)) 344 break; 345 hres = do_process_key(&iter, hkey, buf, do_register); 346 if(FAILED(hres)) 347 break; 348 } 349 350 TRACE("%x %x\n", do_register, key_type); 351 if(!do_register && (key_type == NORMAL || key_type == FORCE_REMOVE)) { 352 TRACE("Deleting %s\n", debugstr_w(name.str)); 353 RegDeleteKeyW(parent_key, name.str); 354 } 355 356 if(hkey && key_type != IS_VAL) 357 RegCloseKey(hkey); 358 hkey = 0; 359 name.len = 0; 360 361 hres = get_word(&iter, buf); 362 if(FAILED(hres)) 363 break; 364 } 365 366 HeapFree(GetProcessHeap(), 0, name.str); 367 if(hkey && key_type != IS_VAL) 368 RegCloseKey(hkey); 369 *pstr = iter; 370 return hres; 371 } 372 373 static HRESULT do_process_root_key(LPCOLESTR data, BOOL do_register) 374 { 375 LPCOLESTR iter = data; 376 strbuf buf; 377 HRESULT hres; 378 unsigned int i; 379 380 strbuf_init(&buf); 381 hres = get_word(&iter, &buf); 382 if(FAILED(hres)) 383 return hres; 384 385 while(*iter) { 386 if(!buf.len) { 387 WARN("ward.len == 0, failed\n"); 388 hres = DISP_E_EXCEPTION; 389 break; 390 } 391 for(i=0; i<sizeof(root_keys)/sizeof(root_keys[0]); i++) { 392 if(!lstrcmpiW(buf.str, root_keys[i].name)) 393 break; 394 } 395 if(i == sizeof(root_keys)/sizeof(root_keys[0])) { 396 WARN("Wrong root key name: %s\n", debugstr_w(buf.str)); 397 hres = DISP_E_EXCEPTION; 398 break; 399 } 400 hres = get_word(&iter, &buf); 401 if(FAILED(hres)) 402 break; 403 if(buf.str[1] || buf.str[0] != '{') { 404 WARN("Failed, expected '{', got %s\n", debugstr_w(buf.str)); 405 hres = DISP_E_EXCEPTION; 406 break; 407 } 408 hres = do_process_key(&iter, root_keys[i].key, &buf, do_register); 409 if(FAILED(hres)) { 410 WARN("Processing key failed: %08x\n", hres); 411 break; 412 } 413 hres = get_word(&iter, &buf); 414 if(FAILED(hres)) 415 break; 416 } 417 HeapFree(GetProcessHeap(), 0, buf.str); 418 return hres; 419 } 420 421 static HRESULT string_register(Registrar *This, LPCOLESTR data, BOOL do_register) 422 { 423 strbuf buf; 424 HRESULT hres; 425 426 TRACE("(%p %s %x)\n", This, debugstr_w(data), do_register); 427 428 strbuf_init(&buf); 429 hres = do_preprocess(This, data, &buf); 430 if(FAILED(hres)) { 431 WARN("preprocessing failed!\n"); 432 HeapFree(GetProcessHeap(), 0, buf.str); 433 return hres; 434 } 435 436 hres = do_process_root_key(buf.str, do_register); 437 if(FAILED(hres) && do_register) 438 do_process_root_key(buf.str, FALSE); 439 440 HeapFree(GetProcessHeap(), 0, buf.str); 441 return hres; 442 } 443 444 static HRESULT resource_register(Registrar *This, LPCOLESTR resFileName, 445 LPCOLESTR szID, LPCOLESTR szType, BOOL do_register) 446 { 447 HINSTANCE hins; 448 HRSRC src; 449 LPSTR regstra; 450 LPWSTR regstrw; 451 DWORD len, reslen; 452 HRESULT hres; 453 454 hins = LoadLibraryExW(resFileName, NULL, LOAD_LIBRARY_AS_DATAFILE); 455 if(hins) { 456 src = FindResourceW(hins, szID, szType); 457 if(src) { 458 regstra = LoadResource(hins, src); 459 reslen = SizeofResource(hins, src); 460 if(regstra) { 461 len = MultiByteToWideChar(CP_ACP, 0, regstra, reslen, NULL, 0)+1; 462 regstrw = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len*sizeof(WCHAR)); 463 MultiByteToWideChar(CP_ACP, 0, regstra, reslen, regstrw, len); 464 regstrw[len-1] = '\0'; 465 466 hres = string_register(This, regstrw, do_register); 467 468 HeapFree(GetProcessHeap(), 0, regstrw); 469 }else { 470 WARN("could not load resource\n"); 471 hres = HRESULT_FROM_WIN32(GetLastError()); 472 } 473 }else { 474 WARN("Could not find source\n"); 475 hres = HRESULT_FROM_WIN32(GetLastError()); 476 } 477 FreeLibrary(hins); 478 }else { 479 WARN("Could not load resource file\n"); 480 hres = HRESULT_FROM_WIN32(GetLastError()); 481 } 482 483 return hres; 484 } 485 486 static HRESULT file_register(Registrar *This, LPCOLESTR fileName, BOOL do_register) 487 { 488 HANDLE file; 489 DWORD filelen, len; 490 LPWSTR regstrw; 491 LPSTR regstra; 492 HRESULT hres; 493 494 file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 495 if(file != INVALID_HANDLE_VALUE) { 496 filelen = GetFileSize(file, NULL); 497 regstra = HeapAlloc(GetProcessHeap(), 0, filelen); 498 if(ReadFile(file, regstra, filelen, NULL, NULL)) { 499 len = MultiByteToWideChar(CP_ACP, 0, regstra, filelen, NULL, 0)+1; 500 regstrw = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len*sizeof(WCHAR)); 501 MultiByteToWideChar(CP_ACP, 0, regstra, filelen, regstrw, len); 502 regstrw[len-1] = '\0'; 503 504 hres = string_register(This, regstrw, do_register); 505 506 HeapFree(GetProcessHeap(), 0, regstrw); 507 }else { 508 WARN("Failed to read file %s\n", debugstr_w(fileName)); 509 hres = HRESULT_FROM_WIN32(GetLastError()); 510 } 511 HeapFree(GetProcessHeap(), 0, regstra); 512 CloseHandle(file); 513 }else { 514 WARN("Could not open file %s\n", debugstr_w(fileName)); 515 hres = HRESULT_FROM_WIN32(GetLastError()); 516 } 517 518 return hres; 519 } 520 521 static HRESULT WINAPI Registrar_QueryInterface(IRegistrar *iface, REFIID riid, void **ppvObject) 522 { 523 TRACE("(%p)->(%s %p\n", iface, debugstr_guid(riid), ppvObject); 524 525 if(IsEqualGUID(&IID_IUnknown, riid) 526 || IsEqualGUID(&IID_IRegistrar, riid) 527 || IsEqualGUID(&IID_IRegistrarBase, riid)) { 528 IRegistrar_AddRef(iface); 529 *ppvObject = iface; 530 return S_OK; 531 } 532 return E_NOINTERFACE; 533 } 534 535 static ULONG WINAPI Registrar_AddRef(IRegistrar *iface) 536 { 537 Registrar *This = impl_from_IRegistrar(iface); 538 ULONG ref = InterlockedIncrement(&This->ref); 539 TRACE("(%p) ->%d\n", This, ref); 540 return ref; 541 } 542 543 static ULONG WINAPI Registrar_Release(IRegistrar *iface) 544 { 545 Registrar *This = impl_from_IRegistrar(iface); 546 ULONG ref = InterlockedDecrement(&This->ref); 547 548 TRACE("(%p) ->%d\n", This, ref); 549 if(!ref) { 550 IRegistrar_ClearReplacements(iface); 551 HeapFree(GetProcessHeap(), 0, This); 552 } 553 return ref; 554 } 555 556 static HRESULT WINAPI Registrar_AddReplacement(IRegistrar *iface, LPCOLESTR Key, LPCOLESTR item) 557 { 558 Registrar *This = impl_from_IRegistrar(iface); 559 int len; 560 rep_list *new_rep; 561 562 TRACE("(%p)->(%s %s)\n", This, debugstr_w(Key), debugstr_w(item)); 563 564 new_rep = HeapAlloc(GetProcessHeap(), 0, sizeof(rep_list)); 565 566 new_rep->key_len = lstrlenW(Key); 567 new_rep->key = HeapAlloc(GetProcessHeap(), 0, (new_rep->key_len + 1) * sizeof(OLECHAR)); 568 memcpy(new_rep->key, Key, (new_rep->key_len+1)*sizeof(OLECHAR)); 569 570 len = lstrlenW(item)+1; 571 new_rep->item = HeapAlloc(GetProcessHeap(), 0, len*sizeof(OLECHAR)); 572 memcpy(new_rep->item, item, len*sizeof(OLECHAR)); 573 574 new_rep->next = This->rep; 575 This->rep = new_rep; 576 577 return S_OK; 578 } 579 580 static HRESULT WINAPI Registrar_ClearReplacements(IRegistrar *iface) 581 { 582 Registrar *This = impl_from_IRegistrar(iface); 583 rep_list *iter, *iter2; 584 585 TRACE("(%p)\n", This); 586 587 if(!This->rep) 588 return S_OK; 589 590 iter = This->rep; 591 while(iter) { 592 iter2 = iter->next; 593 HeapFree(GetProcessHeap(), 0, iter->key); 594 HeapFree(GetProcessHeap(), 0, iter->item); 595 HeapFree(GetProcessHeap(), 0, iter); 596 iter = iter2; 597 } 598 599 This->rep = NULL; 600 return S_OK; 601 } 602 603 static HRESULT WINAPI Registrar_ResourceRegisterSz(IRegistrar* iface, LPCOLESTR resFileName, 604 LPCOLESTR szID, LPCOLESTR szType) 605 { 606 Registrar *This = impl_from_IRegistrar(iface); 607 TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(resFileName), debugstr_w(szID), debugstr_w(szType)); 608 return resource_register(This, resFileName, szID, szType, TRUE); 609 } 610 611 static HRESULT WINAPI Registrar_ResourceUnregisterSz(IRegistrar* iface, LPCOLESTR resFileName, 612 LPCOLESTR szID, LPCOLESTR szType) 613 { 614 Registrar *This = impl_from_IRegistrar(iface); 615 TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(resFileName), debugstr_w(szID), debugstr_w(szType)); 616 return resource_register(This, resFileName, szID, szType, FALSE); 617 } 618 619 static HRESULT WINAPI Registrar_FileRegister(IRegistrar* iface, LPCOLESTR fileName) 620 { 621 Registrar *This = impl_from_IRegistrar(iface); 622 TRACE("(%p)->(%s)\n", This, debugstr_w(fileName)); 623 return file_register(This, fileName, TRUE); 624 } 625 626 static HRESULT WINAPI Registrar_FileUnregister(IRegistrar* iface, LPCOLESTR fileName) 627 { 628 Registrar *This = impl_from_IRegistrar(iface); 629 FIXME("(%p)->(%s)\n", This, debugstr_w(fileName)); 630 return file_register(This, fileName, FALSE); 631 } 632 633 static HRESULT WINAPI Registrar_StringRegister(IRegistrar* iface, LPCOLESTR data) 634 { 635 Registrar *This = impl_from_IRegistrar(iface); 636 TRACE("(%p)->(%s)\n", This, debugstr_w(data)); 637 return string_register(This, data, TRUE); 638 } 639 640 static HRESULT WINAPI Registrar_StringUnregister(IRegistrar* iface, LPCOLESTR data) 641 { 642 Registrar *This = impl_from_IRegistrar(iface); 643 TRACE("(%p)->(%s)\n", This, debugstr_w(data)); 644 return string_register(This, data, FALSE); 645 } 646 647 static HRESULT WINAPI Registrar_ResourceRegister(IRegistrar* iface, LPCOLESTR resFileName, 648 UINT nID, LPCOLESTR szType) 649 { 650 Registrar *This = impl_from_IRegistrar(iface); 651 TRACE("(%p)->(%s %d %s)\n", iface, debugstr_w(resFileName), nID, debugstr_w(szType)); 652 return resource_register(This, resFileName, MAKEINTRESOURCEW(nID), szType, TRUE); 653 } 654 655 static HRESULT WINAPI Registrar_ResourceUnregister(IRegistrar* iface, LPCOLESTR resFileName, 656 UINT nID, LPCOLESTR szType) 657 { 658 Registrar *This = impl_from_IRegistrar(iface); 659 TRACE("(%p)->(%s %d %s)\n", This, debugstr_w(resFileName), nID, debugstr_w(szType)); 660 return resource_register(This, resFileName, MAKEINTRESOURCEW(nID), szType, FALSE); 661 } 662 663 static const IRegistrarVtbl RegistrarVtbl = { 664 Registrar_QueryInterface, 665 Registrar_AddRef, 666 Registrar_Release, 667 Registrar_AddReplacement, 668 Registrar_ClearReplacements, 669 Registrar_ResourceRegisterSz, 670 Registrar_ResourceUnregisterSz, 671 Registrar_FileRegister, 672 Registrar_FileUnregister, 673 Registrar_StringRegister, 674 Registrar_StringUnregister, 675 Registrar_ResourceRegister, 676 Registrar_ResourceUnregister, 677 }; 678 679 /*********************************************************************** 680 * AtlCreateRegistrar [atl100.@] 681 */ 682 HRESULT WINAPI AtlCreateRegistrar(IRegistrar **ret) 683 { 684 Registrar *registrar; 685 686 registrar = HeapAlloc(GetProcessHeap(), 0, sizeof(*registrar)); 687 if(!registrar) 688 return E_OUTOFMEMORY; 689 690 registrar->IRegistrar_iface.lpVtbl = &RegistrarVtbl; 691 registrar->ref = 1; 692 registrar->rep = NULL; 693 694 *ret = ®istrar->IRegistrar_iface; 695 return S_OK; 696 } 697 698 /*********************************************************************** 699 * AtlUpdateRegistryFromResourceD [atl100.@] 700 */ 701 HRESULT WINAPI AtlUpdateRegistryFromResourceD(HINSTANCE inst, LPCOLESTR res, 702 BOOL bRegister, struct _ATL_REGMAP_ENTRY *pMapEntries, IRegistrar *pReg) 703 { 704 const struct _ATL_REGMAP_ENTRY *iter; 705 WCHAR module_name[MAX_PATH]; 706 IRegistrar *registrar; 707 HRESULT hres; 708 709 static const WCHAR moduleW[] = {'M','O','D','U','L','E',0}; 710 static const WCHAR registryW[] = {'R','E','G','I','S','T','R','Y',0}; 711 712 if(!GetModuleFileNameW(inst, module_name, MAX_PATH)) { 713 FIXME("hinst %p: did not get module name\n", inst); 714 return E_FAIL; 715 } 716 717 TRACE("%p (%s), %s, %d, %p, %p\n", inst, debugstr_w(module_name), 718 debugstr_w(res), bRegister, pMapEntries, pReg); 719 720 if(pReg) { 721 registrar = pReg; 722 }else { 723 hres = AtlCreateRegistrar(®istrar); 724 if(FAILED(hres)) 725 return hres; 726 } 727 728 IRegistrar_AddReplacement(registrar, moduleW, module_name); 729 730 for (iter = pMapEntries; iter && iter->szKey; iter++) 731 IRegistrar_AddReplacement(registrar, iter->szKey, iter->szData); 732 733 if(bRegister) 734 hres = IRegistrar_ResourceRegisterSz(registrar, module_name, res, registryW); 735 else 736 hres = IRegistrar_ResourceUnregisterSz(registrar, module_name, res, registryW); 737 738 if(registrar != pReg) 739 IRegistrar_Release(registrar); 740 return hres; 741 } 742