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