Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:37559 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 48069 invoked from network); 9 May 2008 10:05:09 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 9 May 2008 10:05:09 -0000 Authentication-Results: pb1.pair.com smtp.mail=hsantos@isdg.net; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=hsantos@isdg.net; sender-id=pass Received-SPF: pass (pb1.pair.com: domain isdg.net designates 208.247.131.9 as permitted sender) X-PHP-List-Original-Sender: hsantos@isdg.net X-Host-Fingerprint: 208.247.131.9 ntbbs.winserver.com Windows NT 4.0 (older) Received: from [208.247.131.9] ([208.247.131.9:1378] helo=winserver.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 10/82-34643-4D124284 for ; Fri, 09 May 2008 06:05:09 -0400 Received: from mail.winserver.com ([208.247.131.9]) by winserver.com (Wildcat! SMTP Router v6.3.452.5) for internals@lists.php.net; Fri, 09 May 2008 06:03:48 -0400 Received: from mail.winserver.com ([208.247.131.9]) by winserver.com (Wildcat! SMTP v6.3.452.5) with ESMTP id 768774000; Fri, 09 May 2008 06:03:47 -0400 Message-ID: <4824219D.3070806@isdg.net> Date: Fri, 09 May 2008 06:04:13 -0400 Organization: Santronics Software, Inc. User-Agent: Thunderbird 2.0.0.0 (Windows/20070326) MIME-Version: 1.0 To: internals@lists.php.net Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Extention_Dir From: hsantos@isdg.net (Hector Santos) I'm relatively new to PHP development. I hope this is the appropriate area for this question since I was thinking maybe I could use the opportunity to get involved with the internals by making a patch regarding how DLLs are loaded. Specifically, the extension_dir="path" directive which only allows a single path for finding dlls. I'm nearly done with a new Windows-based PHP extension (php_wildcat.dll) and one of the issues was DLL dependencies. The PHP extension offers direct SDK/API support for our application server and all our DLLs are in a specific server folder. The installation of the Extension is preferred to be placed in our server folder so ideally, something like so would be ideal: extension_dir="./ext;c:/wildcat" But of course, this isn't supported and it will not work, in fact, it fails the loading of other PHP extensions. The official method of placing extensions in the PHP "./Ext" requires that we alter our long (12 years) recommended policy of a) not copying our DLLS to other folders (for auto update/version control reasons) or not requiring of adding the server folder in the Windows PATH. I came up with an somewhat "kludgy" solution but I somewhat feel this has to be a common PHP extension issues with extension authors, thus maybe I must of a missed something where I don't have to do any of this. The solution I came up with is to use DELAY LOADING where the extension is compiled and linked with delayed loading of implicit dlls. For example: the extension is compiled/linked using pragma directives like so: #define USE_DELAY_LOADING ... #ifdef USE_DELAY_LOADING # pragma comment(lib, "delayimp.lib") # pragma comment(linker, "/delayload:wcsrv2.dll") # pragma comment(linker, "/delayload:door32.dll") #endif delayimp.lib is part of the VC6.0 C/C++ runtime library and it handles the delayed implicit loading of dlls. The DLLs above are part of our RPC server API interface. Now, our RPC server folder is recorded in the registry so using the dll entry point DllMain(), the registry location is read and this is used to add to the process environment path. So I have this at the end of my PHP_WILDCAT.CPP code: #ifdef USE_DELAY_LOADING #define GETENV GetEnvironmentVariable #define SETENV SetEnvironmentVariable BOOL GetRegistry(const TCHAR *key, const TCHAR *name, DWORD type, void *data, DWORD datasize) { BOOL ok = FALSE; HKEY k; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &k) == ERROR_SUCCESS) { DWORD t; if (RegQueryValueEx(k, (TCHAR *)name, NULL, &t, (BYTE *)data, &datasize) == ERROR_SUCCESS) { ok = t == type; } RegCloseKey(k); } return ok; } BOOL GetRegistryString(const TCHAR *name, TCHAR *data, DWORD datasize, const TCHAR *key = "SOFTWARE\\SSI\\Wildcat") { return GetRegistry(key, name, REG_SZ, data, datasize); } BOOL PrepareWildcatPath() { char srvPath[MAX_PATH]={0}; if (GetRegistryString("ServerDirectory",srvPath,MAX_PATH-1)) { char ePath[1024*4] = {0}; strcpy(ePath,srvPath); strcat(ePath,";"); DWORD dw = strlen(ePath); return (GETENV("PATH",&ePath[dw],sizeof(ePath)-dw) && SETENV("PATH",ePath)); } return FALSE; } //////////////////////////////////////////////////////////////////// // DllMain //////////////////////////////////////////////////////////////////// BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID) { switch (dwReason) { case DLL_PROCESS_ATTACH: PrepareWildcatPath(); break; } return TRUE; } #endif This works really well. We can install PHP*.DLLs in the PHP "./EXT" folder and when the extension is loaded by PHP, all of its dependencies are now resolved during the temporary PHP runtime residence time. I could of gone deeper (and more elegant without having to alter the process PATH) by using the delayimp.lib helper hooks available which will issue a callback for the delayed implicit dlls. But seems overly complexed and before I begin on that I wanted so see if a) there was already a method to address this and/or b) I could patch PHP to offer an multi-path extension_dir method. Ideally we would love to keep our specific PHP*.DLL files in our server folder and have extension_dir defined to look at multiple paths. Comments? TIA -- Hector Santos