Module: motley Author: Seth LaForge Synopsis: Top level program for OLE type library walker Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND define macro check-winfunc { check-winfunc(?:name(?args:*)) } => { let (status :: type-union(, ), #rest rest) = ?name(?args); if (status ~= $ERROR-SUCCESS) error("Error in %s: %s", ?"name", win32-error-message(status)); end if; let rest = as(, rest); apply(values, rest) } { check-winfunc(?operation:expression, ?:expression) } => { let (status :: type-union(, ), #rest rest) = ?expression; if (status ~= $ERROR-SUCCESS) error("Error while %s: %s", ?operation, win32-error-message(status)); end if; let rest = as(, rest); apply(values, rest) } end macro check-winfunc; define macro with-key { with-key (?:name = ?key:expression, ?subkey:expression) ?:body end } => { let ?name :: = check-winfunc(RegOpenKeyEx(?key, ?subkey, 0, $KEY-QUERY-VALUE + $KEY-ENUMERATE-SUB-KEYS)); block () ?body cleanup check-winfunc(RegCloseKey(?name)); end; } end macro with-key; define function registry-key-string-value (key :: , value-name :: false-or()) => (r :: false-or()) let r = make(, size: 1024); with-stack-structure (length :: ) pointer-value(length) := 1024; let val :: = value-name | null-pointer(); let (status, type) = RegQueryValueEx(key, null-pointer(), val, r, length); if (status = $ERROR-SUCCESS & type = $REG-SZ) r end if end with-stack-structure end function registry-key-string-value; define macro with-subkeys { with-subkeys(?:name, ?subkey:name = ?key:expression) ?:body end } => { with-stack-structure (?name :: , size: 1024) for (index from 0, until: begin let status = RegEnumKey(?key, index, ?name, 1024); if (status ~= $ERROR-NO-MORE-ITEMS) check-winfunc("RegEnumKey", status) end; status = $ERROR-NO-MORE-ITEMS end) with-key (?subkey = ?key, ?name) ?body end with-key; end for; end with-stack-structure; } end macro with-subkeys; /* define macro with { with () ?:body end } => { ?body } { with (?:name ?rest:*; ?next:*) ?:body end } => { "with-" ## ?name (?rest) with (?next) ?body end end } end macro with; */ define function hex-to-integer (hex :: ) => (r :: ) let r :: = 0; for (char in hex) r := r * 16 + if ('0' <= char & char <= '9') as(, char) - as(, '0') else as(, as-uppercase(char)) - as(, 'A') end if; end for; r end function hex-to-integer; define constant = ; define constant registry-type-library-name = head; define constant registry-type-library-path = tail; // Reads the list of type libraries from the registry and returns information // about type library names and locations. // r: sequence of type library descriptions. // r[*].registry-type-library-name: a describing a type library. // r[*].registry-type-library-path: a with the path of a type // library. define function get-registry-type-libraries () => (r :: ) let r = make(); let hkey :: = $HKEY-CLASSES-ROOT; with-key (typelibs = hkey, "TypeLib") with-subkeys (libid-name, libid = typelibs) // For all versions: with-subkeys (libver-name, libver = libid) // Get the library name: let libname = registry-key-string-value(libver, #f) | ""; // For all languages: with-subkeys (langid-name, langid-key = libver) // To be a langid, it must be all digits: if (every?(char-is-hex?, langid-name)) let langid :: = hex-to-integer(langid-name); with-stack-structure (c-langname :: , size: 1024) let langname :: = c-langname; if (0 = GetLocaleInfo(MAKELCID(langid, $SORT-DEFAULT), $LOCALE-SLANGUAGE, c-langname, 1024)) langname := ""; end if; block () with-key (win32-key = langid-key, "win32") let win32-location = registry-key-string-value(win32-key, #f); if (win32-location) push-last(r, pair( concatenate-as(, libname, " (", libver-name, ") ", langname), concatenate-as(, win32-location))); end if; end with-key; exception (x :: ) // Ignore exceptions. end block; end with-stack-structure; end if; end with-subkeys; end with-subkeys; end with-subkeys; end with-key; r := sort!(r, test: method (a,b) a.registry-type-library-name.as-lowercase < b.registry-type-library-name.as-lowercase end method) end function get-registry-type-libraries; // Extract the short name of a type library. If there are any problems // opening the type library, an will be signalled. // DEPRECATED in favor of get-type-library-information. define function get-type-library-short-name (path :: type-union(, )) => (short-name :: ) get-type-library-information(path) end function get-type-library-short-name; // Extract the short name of a type library. // Also get the names of all of the interfaces and coclasses in a type library, // as candidates for the interface section of a spec file. // If there are any problems opening the type library, an will be // signalled. define function get-type-library-information (path :: type-union(, )) => (short-name :: , interfaces :: ) with-ole let lib = make(, file: path); let interfaces = make(); for (entry in lib.contents) if (instance?(entry, ) | instance?(entry, )) if (~ member?(entry.c-name, interfaces, test: \=)) push-last(interfaces, entry.c-name); end if; end if; end for; values(lib.dylan-name, interfaces) end with-ole end function get-type-library-information;