| 1 | /* $Id: shell.c,v 1.2 2001-10-17 09:15:20 phaller Exp $ */ | 
|---|
| 2 | /* | 
|---|
| 3 | *                              Shell Library Functions | 
|---|
| 4 | * | 
|---|
| 5 | *  1998 Marcus Meissner | 
|---|
| 6 | */ | 
|---|
| 7 | #ifdef __WIN32OS2__ | 
|---|
| 8 | #define ICOM_CINTERFACE 1 | 
|---|
| 9 | #include <odin.h> | 
|---|
| 10 | #endif | 
|---|
| 11 | #include <stdlib.h> | 
|---|
| 12 | #include <string.h> | 
|---|
| 13 | #ifndef __WIN32OS2__ | 
|---|
| 14 | #include <unistd.h> | 
|---|
| 15 | #endif | 
|---|
| 16 | #include <ctype.h> | 
|---|
| 17 | #include "windef.h" | 
|---|
| 18 | #include "wingdi.h" | 
|---|
| 19 | #include "wine/winuser16.h" | 
|---|
| 20 | #include "wine/winbase16.h" | 
|---|
| 21 | #include "wine/shell16.h" | 
|---|
| 22 | #include "winerror.h" | 
|---|
| 23 | #include "heap.h" | 
|---|
| 24 | #include "ldt.h" | 
|---|
| 25 | #include "module.h" | 
|---|
| 26 | #include "neexe.h" | 
|---|
| 27 | #include "dlgs.h" | 
|---|
| 28 | #include "cursoricon.h" | 
|---|
| 29 | #include "shellapi.h" | 
|---|
| 30 | #include "shlobj.h" | 
|---|
| 31 | #include "debugtools.h" | 
|---|
| 32 | #include "winreg.h" | 
|---|
| 33 | #ifndef __WIN32OS2__ | 
|---|
| 34 | #include "syslevel.h" | 
|---|
| 35 | #else | 
|---|
| 36 | #include <heapstring.h> | 
|---|
| 37 | #endif | 
|---|
| 38 | #include "shlwapi.h" | 
|---|
| 39 |  | 
|---|
| 40 | DEFAULT_DEBUG_CHANNEL(shell); | 
|---|
| 41 | DECLARE_DEBUG_CHANNEL(exec); | 
|---|
| 42 |  | 
|---|
| 43 | /* .ICO file ICONDIR definitions */ | 
|---|
| 44 |  | 
|---|
| 45 | #include "pshpack1.h" | 
|---|
| 46 |  | 
|---|
| 47 | typedef struct | 
|---|
| 48 | { | 
|---|
| 49 | BYTE        bWidth;          /* Width, in pixels, of the image      */ | 
|---|
| 50 | BYTE        bHeight;         /* Height, in pixels, of the image     */ | 
|---|
| 51 | BYTE        bColorCount;     /* Number of colors in image (0 if >=8bpp) */ | 
|---|
| 52 | BYTE        bReserved;       /* Reserved ( must be 0)               */ | 
|---|
| 53 | WORD        wPlanes;         /* Color Planes                        */ | 
|---|
| 54 | WORD        wBitCount;       /* Bits per pixel                      */ | 
|---|
| 55 | DWORD       dwBytesInRes;    /* How many bytes in this resource?    */ | 
|---|
| 56 | DWORD       dwImageOffset;   /* Where in the file is this image?    */ | 
|---|
| 57 | } icoICONDIRENTRY, *LPicoICONDIRENTRY; | 
|---|
| 58 |  | 
|---|
| 59 | typedef struct | 
|---|
| 60 | { | 
|---|
| 61 | WORD            idReserved;   /* Reserved (must be 0)               */ | 
|---|
| 62 | WORD            idType;       /* Resource Type (1 for icons)        */ | 
|---|
| 63 | WORD            idCount;      /* How many images?                   */ | 
|---|
| 64 | icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */ | 
|---|
| 65 | } icoICONDIR, *LPicoICONDIR; | 
|---|
| 66 |  | 
|---|
| 67 | #include "poppack.h" | 
|---|
| 68 |  | 
|---|
| 69 | static const char*      lpstrMsgWndCreated = "OTHERWINDOWCREATED"; | 
|---|
| 70 | static const char*      lpstrMsgWndDestroyed = "OTHERWINDOWDESTROYED"; | 
|---|
| 71 | static const char*      lpstrMsgShellActivate = "ACTIVATESHELLWINDOW"; | 
|---|
| 72 |  | 
|---|
| 73 | static HWND16   SHELL_hWnd = 0; | 
|---|
| 74 | static HHOOK    SHELL_hHook = 0; | 
|---|
| 75 | static UINT16   uMsgWndCreated = 0; | 
|---|
| 76 | static UINT16   uMsgWndDestroyed = 0; | 
|---|
| 77 | static UINT16   uMsgShellActivate = 0; | 
|---|
| 78 | HINSTANCE16     SHELL_hInstance = 0; | 
|---|
| 79 | HINSTANCE SHELL_hInstance32; | 
|---|
| 80 | static int SHELL_Attach = 0; | 
|---|
| 81 |  | 
|---|
| 82 | /*********************************************************************** | 
|---|
| 83 | * SHELL_DllEntryPoint [SHELL.entry] | 
|---|
| 84 | * | 
|---|
| 85 | * Initialization code for shell.dll. Automatically loads the | 
|---|
| 86 | * 32-bit shell32.dll to allow thunking up to 32-bit code. | 
|---|
| 87 | * | 
|---|
| 88 | * RETURNS: | 
|---|
| 89 | */ | 
|---|
| 90 | BOOL WINAPI SHELL_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, | 
|---|
| 91 | WORD ds, WORD HeapSize, DWORD res1, WORD res2) | 
|---|
| 92 | { | 
|---|
| 93 | TRACE("(%08lx, %04x, %04x, %04x, %08lx, %04x)\n", | 
|---|
| 94 | Reason, hInst, ds, HeapSize, res1, res2); | 
|---|
| 95 |  | 
|---|
| 96 | switch(Reason) | 
|---|
| 97 | { | 
|---|
| 98 | case DLL_PROCESS_ATTACH: | 
|---|
| 99 | SHELL_Attach++; | 
|---|
| 100 | if (SHELL_hInstance) | 
|---|
| 101 | { | 
|---|
| 102 | ERR("shell.dll instantiated twice!\n"); | 
|---|
| 103 | /* | 
|---|
| 104 | * We should return FALSE here, but that will break | 
|---|
| 105 | * most apps that use CreateProcess because we do | 
|---|
| 106 | * not yet support seperate address-spaces. | 
|---|
| 107 | */ | 
|---|
| 108 | return TRUE; | 
|---|
| 109 | } | 
|---|
| 110 |  | 
|---|
| 111 | SHELL_hInstance = hInst; | 
|---|
| 112 | if(!SHELL_hInstance32) | 
|---|
| 113 | { | 
|---|
| 114 | if(!(SHELL_hInstance32 = LoadLibraryA("shell32.dll"))) | 
|---|
| 115 | { | 
|---|
| 116 | ERR("Could not load sibling shell32.dll\n"); | 
|---|
| 117 | return FALSE; | 
|---|
| 118 | } | 
|---|
| 119 | } | 
|---|
| 120 | break; | 
|---|
| 121 |  | 
|---|
| 122 | case DLL_PROCESS_DETACH: | 
|---|
| 123 | if(!--SHELL_Attach) | 
|---|
| 124 | { | 
|---|
| 125 | SHELL_hInstance = 0; | 
|---|
| 126 | if(SHELL_hInstance32) | 
|---|
| 127 | FreeLibrary(SHELL_hInstance32); | 
|---|
| 128 | } | 
|---|
| 129 | break; | 
|---|
| 130 | } | 
|---|
| 131 | return TRUE; | 
|---|
| 132 | } | 
|---|
| 133 |  | 
|---|
| 134 | #ifndef __WIN32OS2__ | 
|---|
| 135 | /************************************************************************* | 
|---|
| 136 | *                              DragAcceptFiles16               [SHELL.9] | 
|---|
| 137 | */ | 
|---|
| 138 | void WINAPI DragAcceptFiles16(HWND16 hWnd, BOOL16 b) | 
|---|
| 139 | { | 
|---|
| 140 | DragAcceptFiles(hWnd, b); | 
|---|
| 141 | } | 
|---|
| 142 |  | 
|---|
| 143 | /************************************************************************* | 
|---|
| 144 | *                              DragQueryFile16         [SHELL.11] | 
|---|
| 145 | */ | 
|---|
| 146 | UINT16 WINAPI DragQueryFile16( | 
|---|
| 147 | HDROP16 hDrop, | 
|---|
| 148 | WORD wFile, | 
|---|
| 149 | LPSTR lpszFile, | 
|---|
| 150 | WORD wLength) | 
|---|
| 151 | { | 
|---|
| 152 | LPSTR lpDrop; | 
|---|
| 153 | UINT i = 0; | 
|---|
| 154 | LPDROPFILESTRUCT16 lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop); | 
|---|
| 155 |  | 
|---|
| 156 | TRACE("(%04x, %x, %p, %u)\n", hDrop,wFile,lpszFile,wLength); | 
|---|
| 157 |  | 
|---|
| 158 | if(!lpDropFileStruct) goto end; | 
|---|
| 159 |  | 
|---|
| 160 | lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize; | 
|---|
| 161 | wFile = (wFile==0xffff) ? 0xffffffff : wFile; | 
|---|
| 162 |  | 
|---|
| 163 | while (i++ < wFile) | 
|---|
| 164 | { | 
|---|
| 165 | while (*lpDrop++); /* skip filename */ | 
|---|
| 166 | if (!*lpDrop) | 
|---|
| 167 | { | 
|---|
| 168 | i = (wFile == 0xFFFFFFFF) ? i : 0; | 
|---|
| 169 | goto end; | 
|---|
| 170 | } | 
|---|
| 171 | } | 
|---|
| 172 |  | 
|---|
| 173 | i = strlen(lpDrop); | 
|---|
| 174 | i++; | 
|---|
| 175 | if (!lpszFile ) goto end;   /* needed buffer size */ | 
|---|
| 176 | i = (wLength > i) ? i : wLength; | 
|---|
| 177 | lstrcpynA (lpszFile,  lpDrop,  i); | 
|---|
| 178 | end: | 
|---|
| 179 | GlobalUnlock16(hDrop); | 
|---|
| 180 | return i; | 
|---|
| 181 | } | 
|---|
| 182 |  | 
|---|
| 183 | /************************************************************************* | 
|---|
| 184 | *                              DragFinish16            [SHELL.12] | 
|---|
| 185 | */ | 
|---|
| 186 | void WINAPI DragFinish16(HDROP16 h) | 
|---|
| 187 | { | 
|---|
| 188 | TRACE("\n"); | 
|---|
| 189 | GlobalFree16((HGLOBAL16)h); | 
|---|
| 190 | } | 
|---|
| 191 |  | 
|---|
| 192 |  | 
|---|
| 193 | /************************************************************************* | 
|---|
| 194 | *                              DragQueryPoint16                [SHELL.13] | 
|---|
| 195 | */ | 
|---|
| 196 | BOOL16 WINAPI DragQueryPoint16(HDROP16 hDrop, POINT16 *p) | 
|---|
| 197 | { | 
|---|
| 198 | LPDROPFILESTRUCT16 lpDropFileStruct; | 
|---|
| 199 | BOOL16           bRet; | 
|---|
| 200 | TRACE("\n"); | 
|---|
| 201 | lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop); | 
|---|
| 202 |  | 
|---|
| 203 | memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16)); | 
|---|
| 204 | bRet = lpDropFileStruct->fInNonClientArea; | 
|---|
| 205 |  | 
|---|
| 206 | GlobalUnlock16(hDrop); | 
|---|
| 207 | return bRet; | 
|---|
| 208 | } | 
|---|
| 209 |  | 
|---|
| 210 | /************************************************************************* | 
|---|
| 211 | *      SHELL_FindExecutable [Internal] | 
|---|
| 212 | * | 
|---|
| 213 | * Utility for code sharing between FindExecutable and ShellExecute | 
|---|
| 214 | */ | 
|---|
| 215 | HINSTANCE SHELL_FindExecutable( LPCSTR lpFile, | 
|---|
| 216 | LPCSTR lpOperation, | 
|---|
| 217 | LPSTR lpResult) | 
|---|
| 218 | { char *extension = NULL; /* pointer to file extension */ | 
|---|
| 219 | char tmpext[5];         /* local copy to mung as we please */ | 
|---|
| 220 | char filetype[256];     /* registry name for this filetype */ | 
|---|
| 221 | LONG filetypelen=256;   /* length of above */ | 
|---|
| 222 | char command[256];      /* command from registry */ | 
|---|
| 223 | LONG commandlen=256;    /* This is the most DOS can handle :) */ | 
|---|
| 224 | char buffer[256];       /* Used to GetProfileString */ | 
|---|
| 225 | HINSTANCE retval=31;  /* default - 'No association was found' */ | 
|---|
| 226 | char *tok;              /* token pointer */ | 
|---|
| 227 | int i;                  /* random counter */ | 
|---|
| 228 | char xlpFile[256] = ""; /* result of SearchPath */ | 
|---|
| 229 |  | 
|---|
| 230 | TRACE("%s\n", (lpFile != NULL?lpFile:"-") ); | 
|---|
| 231 |  | 
|---|
| 232 | lpResult[0]='\0'; /* Start off with an empty return string */ | 
|---|
| 233 |  | 
|---|
| 234 | /* trap NULL parameters on entry */ | 
|---|
| 235 | if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL )) | 
|---|
| 236 | { WARN_(exec)("(lpFile=%s,lpResult=%s,lpOperation=%s): NULL parameter\n", | 
|---|
| 237 | lpFile, lpOperation, lpResult); | 
|---|
| 238 | return 2; /* File not found. Close enough, I guess. */ | 
|---|
| 239 | } | 
|---|
| 240 |  | 
|---|
| 241 | if (SearchPathA( NULL, lpFile,".exe",sizeof(xlpFile),xlpFile,NULL)) | 
|---|
| 242 | { TRACE("SearchPathA returned non-zero\n"); | 
|---|
| 243 | lpFile = xlpFile; | 
|---|
| 244 | } | 
|---|
| 245 |  | 
|---|
| 246 | /* First thing we need is the file's extension */ | 
|---|
| 247 | extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */ | 
|---|
| 248 | /* File->Run in progman uses */ | 
|---|
| 249 | /* .\FILE.EXE :( */ | 
|---|
| 250 | TRACE("xlpFile=%s,extension=%s\n", xlpFile, extension); | 
|---|
| 251 |  | 
|---|
| 252 | if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)])) | 
|---|
| 253 | { WARN("Returning 31 - No association\n"); | 
|---|
| 254 | return 31; /* no association */ | 
|---|
| 255 | } | 
|---|
| 256 |  | 
|---|
| 257 | /* Make local copy & lowercase it for reg & 'programs=' lookup */ | 
|---|
| 258 | lstrcpynA( tmpext, extension, 5 ); | 
|---|
| 259 | CharLowerA( tmpext ); | 
|---|
| 260 | TRACE("%s file\n", tmpext); | 
|---|
| 261 |  | 
|---|
| 262 | /* Three places to check: */ | 
|---|
| 263 | /* 1. win.ini, [windows], programs (NB no leading '.') */ | 
|---|
| 264 | /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */ | 
|---|
| 265 | /* 3. win.ini, [extensions], extension (NB no leading '.' */ | 
|---|
| 266 | /* All I know of the order is that registry is checked before */ | 
|---|
| 267 | /* extensions; however, it'd make sense to check the programs */ | 
|---|
| 268 | /* section first, so that's what happens here. */ | 
|---|
| 269 |  | 
|---|
| 270 | /* See if it's a program - if GetProfileString fails, we skip this | 
|---|
| 271 | * section. Actually, if GetProfileString fails, we've probably | 
|---|
| 272 | * got a lot more to worry about than running a program... */ | 
|---|
| 273 | if ( GetProfileStringA("windows", "programs", "exe pif bat com", | 
|---|
| 274 | buffer, sizeof(buffer)) > 0 ) | 
|---|
| 275 | { for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]); | 
|---|
| 276 |  | 
|---|
| 277 | tok = strtok(buffer, " \t"); /* ? */ | 
|---|
| 278 | while( tok!= NULL) | 
|---|
| 279 | { | 
|---|
| 280 | if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */ | 
|---|
| 281 | { | 
|---|
| 282 | strcpy(lpResult, xlpFile); | 
|---|
| 283 | /* Need to perhaps check that the file has a path | 
|---|
| 284 | * attached */ | 
|---|
| 285 | TRACE("found %s\n", lpResult); | 
|---|
| 286 | return 33; | 
|---|
| 287 |  | 
|---|
| 288 | /* Greater than 32 to indicate success FIXME According to the | 
|---|
| 289 | * docs, I should be returning a handle for the | 
|---|
| 290 | * executable. Does this mean I'm supposed to open the | 
|---|
| 291 | * executable file or something? More RTFM, I guess... */ | 
|---|
| 292 | } | 
|---|
| 293 | tok=strtok(NULL, " \t"); | 
|---|
| 294 | } | 
|---|
| 295 | } | 
|---|
| 296 |  | 
|---|
| 297 | /* Check registry */ | 
|---|
| 298 | if (RegQueryValue16( HKEY_CLASSES_ROOT, tmpext, filetype, | 
|---|
| 299 | &filetypelen ) == ERROR_SUCCESS ) | 
|---|
| 300 | { | 
|---|
| 301 | filetype[filetypelen]='\0'; | 
|---|
| 302 | TRACE("File type: %s\n", filetype); | 
|---|
| 303 |  | 
|---|
| 304 | /* Looking for ...buffer\shell\lpOperation\command */ | 
|---|
| 305 | strcat( filetype, "\\shell\\" ); | 
|---|
| 306 | strcat( filetype, lpOperation ); | 
|---|
| 307 | strcat( filetype, "\\command" ); | 
|---|
| 308 |  | 
|---|
| 309 | if (RegQueryValue16( HKEY_CLASSES_ROOT, filetype, command, | 
|---|
| 310 | &commandlen ) == ERROR_SUCCESS ) | 
|---|
| 311 | { | 
|---|
| 312 | LPSTR tmp; | 
|---|
| 313 | char param[256]; | 
|---|
| 314 | LONG paramlen = 256; | 
|---|
| 315 |  | 
|---|
| 316 |  | 
|---|
| 317 | /* Get the parameters needed by the application | 
|---|
| 318 | from the associated ddeexec key */ | 
|---|
| 319 | tmp = strstr(filetype,"command"); | 
|---|
| 320 | tmp[0] = '\0'; | 
|---|
| 321 | strcat(filetype,"ddeexec"); | 
|---|
| 322 |  | 
|---|
| 323 | if(RegQueryValue16( HKEY_CLASSES_ROOT, filetype, param,¶mlen ) == ERROR_SUCCESS) | 
|---|
| 324 | { | 
|---|
| 325 | strcat(command," "); | 
|---|
| 326 | strcat(command,param); | 
|---|
| 327 | commandlen += paramlen; | 
|---|
| 328 | } | 
|---|
| 329 |  | 
|---|
| 330 | /* Is there a replace() function anywhere? */ | 
|---|
| 331 | command[commandlen]='\0'; | 
|---|
| 332 | strcpy( lpResult, command ); | 
|---|
| 333 | tok=strstr( lpResult, "%1" ); | 
|---|
| 334 | if (tok != NULL) | 
|---|
| 335 | { | 
|---|
| 336 | tok[0]='\0'; /* truncate string at the percent */ | 
|---|
| 337 | strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */ | 
|---|
| 338 | tok=strstr( command, "%1" ); | 
|---|
| 339 | if ((tok!=NULL) && (strlen(tok)>2)) | 
|---|
| 340 | { | 
|---|
| 341 | strcat( lpResult, &tok[2] ); | 
|---|
| 342 | } | 
|---|
| 343 | } | 
|---|
| 344 | retval=33; /* FIXME see above */ | 
|---|
| 345 | } | 
|---|
| 346 | } | 
|---|
| 347 | else /* Check win.ini */ | 
|---|
| 348 | { | 
|---|
| 349 | /* Toss the leading dot */ | 
|---|
| 350 | extension++; | 
|---|
| 351 | if ( GetProfileStringA( "extensions", extension, "", command, | 
|---|
| 352 | sizeof(command)) > 0) | 
|---|
| 353 | { | 
|---|
| 354 | if (strlen(command)!=0) | 
|---|
| 355 | { | 
|---|
| 356 | strcpy( lpResult, command ); | 
|---|
| 357 | tok=strstr( lpResult, "^" ); /* should be ^.extension? */ | 
|---|
| 358 | if (tok != NULL) | 
|---|
| 359 | { | 
|---|
| 360 | tok[0]='\0'; | 
|---|
| 361 | strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */ | 
|---|
| 362 | tok=strstr( command, "^" ); /* see above */ | 
|---|
| 363 | if ((tok != NULL) && (strlen(tok)>5)) | 
|---|
| 364 | { | 
|---|
| 365 | strcat( lpResult, &tok[5]); | 
|---|
| 366 | } | 
|---|
| 367 | } | 
|---|
| 368 | retval=33; /* FIXME - see above */ | 
|---|
| 369 | } | 
|---|
| 370 | } | 
|---|
| 371 | } | 
|---|
| 372 |  | 
|---|
| 373 | TRACE("returning %s\n", lpResult); | 
|---|
| 374 | return retval; | 
|---|
| 375 | } | 
|---|
| 376 | /************************************************************************* | 
|---|
| 377 | *                              ShellExecute16          [SHELL.20] | 
|---|
| 378 | */ | 
|---|
| 379 | HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation, | 
|---|
| 380 | LPCSTR lpFile, LPCSTR lpParameters, | 
|---|
| 381 | LPCSTR lpDirectory, INT16 iShowCmd ) | 
|---|
| 382 | {   HINSTANCE16 retval=31; | 
|---|
| 383 | char old_dir[1024]; | 
|---|
| 384 | char cmd[1024] = ""; | 
|---|
| 385 |  | 
|---|
| 386 | TRACE("(%04x,'%s','%s','%s','%s',%x)\n", | 
|---|
| 387 | hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>", | 
|---|
| 388 | lpParameters ? lpParameters : "<null>", | 
|---|
| 389 | lpDirectory ? lpDirectory : "<null>", iShowCmd); | 
|---|
| 390 |  | 
|---|
| 391 | if (lpFile==NULL) return 0; /* should not happen */ | 
|---|
| 392 | if (lpOperation==NULL) /* default is open */ | 
|---|
| 393 | lpOperation="open"; | 
|---|
| 394 |  | 
|---|
| 395 | if (lpDirectory) | 
|---|
| 396 | { GetCurrentDirectoryA( sizeof(old_dir), old_dir ); | 
|---|
| 397 | SetCurrentDirectoryA( lpDirectory ); | 
|---|
| 398 | } | 
|---|
| 399 |  | 
|---|
| 400 | /* First try to execute lpFile with lpParameters directly */ | 
|---|
| 401 | strcpy(cmd,lpFile); | 
|---|
| 402 | strcat(cmd,lpParameters ? lpParameters : ""); | 
|---|
| 403 |  | 
|---|
| 404 | retval = WinExec16( cmd, iShowCmd ); | 
|---|
| 405 |  | 
|---|
| 406 | /* Unable to execute lpFile directly | 
|---|
| 407 | Check if we can match an application to lpFile */ | 
|---|
| 408 | if(retval < 32) | 
|---|
| 409 | { | 
|---|
| 410 | cmd[0] = '\0'; | 
|---|
| 411 | retval = SHELL_FindExecutable( lpFile, lpOperation, cmd ); | 
|---|
| 412 |  | 
|---|
| 413 | if (retval > 32)  /* Found */ | 
|---|
| 414 | { | 
|---|
| 415 | if (lpParameters) | 
|---|
| 416 | { | 
|---|
| 417 | strcat(cmd," "); | 
|---|
| 418 | strcat(cmd,lpParameters); | 
|---|
| 419 | } | 
|---|
| 420 | retval = WinExec16( cmd, iShowCmd ); | 
|---|
| 421 | } | 
|---|
| 422 | else if(PathIsURLA((LPSTR)lpFile))    /* File not found, check for URL */ | 
|---|
| 423 | { | 
|---|
| 424 | char lpstrProtocol[256]; | 
|---|
| 425 | LONG cmdlen = 512; | 
|---|
| 426 | LPSTR lpstrRes; | 
|---|
| 427 | INT iSize; | 
|---|
| 428 |  | 
|---|
| 429 | lpstrRes = strchr(lpFile,':'); | 
|---|
| 430 | iSize = lpstrRes - lpFile; | 
|---|
| 431 |  | 
|---|
| 432 | /* Looking for ...protocol\shell\lpOperation\command */ | 
|---|
| 433 | strncpy(lpstrProtocol,lpFile,iSize); | 
|---|
| 434 | lpstrProtocol[iSize]='\0'; | 
|---|
| 435 | strcat( lpstrProtocol, "\\shell\\" ); | 
|---|
| 436 | strcat( lpstrProtocol, lpOperation ); | 
|---|
| 437 | strcat( lpstrProtocol, "\\command" ); | 
|---|
| 438 |  | 
|---|
| 439 | /* Remove File Protocol from lpFile */ | 
|---|
| 440 | /* In the case file://path/file     */ | 
|---|
| 441 | if(!strncasecmp(lpFile,"file",iSize)) | 
|---|
| 442 | { | 
|---|
| 443 | lpFile += iSize; | 
|---|
| 444 | while(*lpFile == ':') lpFile++; | 
|---|
| 445 | } | 
|---|
| 446 |  | 
|---|
| 447 |  | 
|---|
| 448 | /* Get the application for the protocol and execute it */ | 
|---|
| 449 | if (RegQueryValue16( HKEY_CLASSES_ROOT, lpstrProtocol, cmd, | 
|---|
| 450 | &cmdlen ) == ERROR_SUCCESS ) | 
|---|
| 451 | { | 
|---|
| 452 | LPSTR tok; | 
|---|
| 453 | LPSTR tmp; | 
|---|
| 454 | char param[256] = ""; | 
|---|
| 455 | LONG paramlen = 256; | 
|---|
| 456 |  | 
|---|
| 457 | /* Get the parameters needed by the application | 
|---|
| 458 | from the associated ddeexec key */ | 
|---|
| 459 | tmp = strstr(lpstrProtocol,"command"); | 
|---|
| 460 | tmp[0] = '\0'; | 
|---|
| 461 | strcat(lpstrProtocol,"ddeexec"); | 
|---|
| 462 |  | 
|---|
| 463 | if(RegQueryValue16( HKEY_CLASSES_ROOT, lpstrProtocol, param,¶mlen ) == ERROR_SUCCESS) | 
|---|
| 464 | { | 
|---|
| 465 | strcat(cmd," "); | 
|---|
| 466 | strcat(cmd,param); | 
|---|
| 467 | cmdlen += paramlen; | 
|---|
| 468 | } | 
|---|
| 469 |  | 
|---|
| 470 | /* Is there a replace() function anywhere? */ | 
|---|
| 471 | cmd[cmdlen]='\0'; | 
|---|
| 472 |  | 
|---|
| 473 | tok=strstr( cmd, "%1" ); | 
|---|
| 474 | if (tok != NULL) | 
|---|
| 475 | { | 
|---|
| 476 | tok[0]='\0'; /* truncate string at the percent */ | 
|---|
| 477 | strcat( cmd, lpFile ); /* what if no dir in xlpFile? */ | 
|---|
| 478 | tok=strstr( cmd, "%1" ); | 
|---|
| 479 | if ((tok!=NULL) && (strlen(tok)>2)) | 
|---|
| 480 | { | 
|---|
| 481 | strcat( cmd, &tok[2] ); | 
|---|
| 482 | } | 
|---|
| 483 | } | 
|---|
| 484 |  | 
|---|
| 485 | retval = WinExec16( cmd, iShowCmd ); | 
|---|
| 486 | } | 
|---|
| 487 | } | 
|---|
| 488 | /* Check if file specified is in the form www.??????.*** */ | 
|---|
| 489 | else if(!strncasecmp(lpFile,"www",3)) | 
|---|
| 490 | { | 
|---|
| 491 | /* if so, append lpFile http:// and call ShellExecute */ | 
|---|
| 492 | char lpstrTmpFile[256] = "http://" ; | 
|---|
| 493 | strcat(lpstrTmpFile,lpFile); | 
|---|
| 494 | retval = ShellExecuteA(hWnd,lpOperation,lpstrTmpFile,NULL,NULL,0); | 
|---|
| 495 | } | 
|---|
| 496 | } | 
|---|
| 497 | if (lpDirectory) | 
|---|
| 498 | SetCurrentDirectoryA( old_dir ); | 
|---|
| 499 | return retval; | 
|---|
| 500 | } | 
|---|
| 501 |  | 
|---|
| 502 | /************************************************************************* | 
|---|
| 503 | *             FindExecutable16   (SHELL.21) | 
|---|
| 504 | */ | 
|---|
| 505 | HINSTANCE16 WINAPI FindExecutable16( LPCSTR lpFile, LPCSTR lpDirectory, | 
|---|
| 506 | LPSTR lpResult ) | 
|---|
| 507 | { return (HINSTANCE16)FindExecutableA( lpFile, lpDirectory, lpResult ); | 
|---|
| 508 | } | 
|---|
| 509 |  | 
|---|
| 510 |  | 
|---|
| 511 | /************************************************************************* | 
|---|
| 512 | *             AboutDlgProc16   (SHELL.33) | 
|---|
| 513 | */ | 
|---|
| 514 | BOOL16 WINAPI AboutDlgProc16( HWND16 hWnd, UINT16 msg, WPARAM16 wParam, | 
|---|
| 515 | LPARAM lParam ) | 
|---|
| 516 | { return AboutDlgProc( hWnd, msg, wParam, lParam ); | 
|---|
| 517 | } | 
|---|
| 518 |  | 
|---|
| 519 |  | 
|---|
| 520 | /************************************************************************* | 
|---|
| 521 | *             ShellAbout16   (SHELL.22) | 
|---|
| 522 | */ | 
|---|
| 523 | BOOL16 WINAPI ShellAbout16( HWND16 hWnd, LPCSTR szApp, LPCSTR szOtherStuff, | 
|---|
| 524 | HICON16 hIcon ) | 
|---|
| 525 | { return ShellAboutA( hWnd, szApp, szOtherStuff, hIcon ); | 
|---|
| 526 | } | 
|---|
| 527 |  | 
|---|
| 528 | /************************************************************************* | 
|---|
| 529 | *                              SHELL_GetResourceTable | 
|---|
| 530 | */ | 
|---|
| 531 | static DWORD SHELL_GetResourceTable(HFILE hFile,LPBYTE *retptr) | 
|---|
| 532 | {       IMAGE_DOS_HEADER        mz_header; | 
|---|
| 533 | char                    magic[4]; | 
|---|
| 534 | int                     size; | 
|---|
| 535 |  | 
|---|
| 536 | TRACE("\n"); | 
|---|
| 537 |  | 
|---|
| 538 | *retptr = NULL; | 
|---|
| 539 | _llseek( hFile, 0, SEEK_SET ); | 
|---|
| 540 | if ((_lread(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) || (mz_header.e_magic != IMAGE_DOS_SIGNATURE)) | 
|---|
| 541 | { /* .ICO file ? */ | 
|---|
| 542 | if (mz_header.e_cblp == 1) | 
|---|
| 543 | { /* ICONHEADER.idType, must be 1 */ | 
|---|
| 544 | *retptr = (LPBYTE)-1; | 
|---|
| 545 | return 1; | 
|---|
| 546 | } | 
|---|
| 547 | else | 
|---|
| 548 | return 0; /* failed */ | 
|---|
| 549 | } | 
|---|
| 550 | _llseek( hFile, mz_header.e_lfanew, SEEK_SET ); | 
|---|
| 551 |  | 
|---|
| 552 | if (_lread( hFile, magic, sizeof(magic) ) != sizeof(magic)) | 
|---|
| 553 | return 0; | 
|---|
| 554 |  | 
|---|
| 555 | _llseek( hFile, mz_header.e_lfanew, SEEK_SET); | 
|---|
| 556 |  | 
|---|
| 557 | if (*(DWORD*)magic  == IMAGE_NT_SIGNATURE) | 
|---|
| 558 | return IMAGE_NT_SIGNATURE; | 
|---|
| 559 |  | 
|---|
| 560 | if (*(WORD*)magic == IMAGE_OS2_SIGNATURE) | 
|---|
| 561 | { IMAGE_OS2_HEADER      ne_header; | 
|---|
| 562 | LPBYTE                pTypeInfo = (LPBYTE)-1; | 
|---|
| 563 |  | 
|---|
| 564 | if (_lread(hFile,&ne_header,sizeof(ne_header))!=sizeof(ne_header)) | 
|---|
| 565 | return 0; | 
|---|
| 566 |  | 
|---|
| 567 | if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) | 
|---|
| 568 | return 0; | 
|---|
| 569 |  | 
|---|
| 570 | size = ne_header.ne_restab - ne_header.ne_rsrctab; | 
|---|
| 571 |  | 
|---|
| 572 | if( size > sizeof(NE_TYPEINFO) ) | 
|---|
| 573 | { pTypeInfo = (BYTE*)HeapAlloc( GetProcessHeap(), 0, size); | 
|---|
| 574 | if( pTypeInfo ) | 
|---|
| 575 | { _llseek(hFile, mz_header.e_lfanew+ne_header.ne_rsrctab, SEEK_SET); | 
|---|
| 576 | if( _lread( hFile, (char*)pTypeInfo, size) != size ) | 
|---|
| 577 | { HeapFree( GetProcessHeap(), 0, pTypeInfo); | 
|---|
| 578 | pTypeInfo = NULL; | 
|---|
| 579 | } | 
|---|
| 580 | } | 
|---|
| 581 | } | 
|---|
| 582 | *retptr = pTypeInfo; | 
|---|
| 583 | return IMAGE_OS2_SIGNATURE; | 
|---|
| 584 | } | 
|---|
| 585 | return 0; /* failed */ | 
|---|
| 586 | } | 
|---|
| 587 |  | 
|---|
| 588 | /************************************************************************* | 
|---|
| 589 | *                      SHELL_LoadResource | 
|---|
| 590 | */ | 
|---|
| 591 | static HGLOBAL16 SHELL_LoadResource(HINSTANCE16 hInst, HFILE hFile, NE_NAMEINFO* pNInfo, WORD sizeShift) | 
|---|
| 592 | {       BYTE*  ptr; | 
|---|
| 593 | HGLOBAL16 handle = DirectResAlloc16( hInst, 0x10, (DWORD)pNInfo->length << sizeShift); | 
|---|
| 594 |  | 
|---|
| 595 | TRACE("\n"); | 
|---|
| 596 |  | 
|---|
| 597 | if( (ptr = (BYTE*)GlobalLock16( handle )) ) | 
|---|
| 598 | { _llseek( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET); | 
|---|
| 599 | _lread( hFile, (char*)ptr, pNInfo->length << sizeShift); | 
|---|
| 600 | return handle; | 
|---|
| 601 | } | 
|---|
| 602 | return 0; | 
|---|
| 603 | } | 
|---|
| 604 |  | 
|---|
| 605 | /************************************************************************* | 
|---|
| 606 | *                      ICO_LoadIcon | 
|---|
| 607 | */ | 
|---|
| 608 | static HGLOBAL16 ICO_LoadIcon(HINSTANCE16 hInst, HFILE hFile, LPicoICONDIRENTRY lpiIDE) | 
|---|
| 609 | {       BYTE*  ptr; | 
|---|
| 610 | HGLOBAL16 handle = DirectResAlloc16( hInst, 0x10, lpiIDE->dwBytesInRes); | 
|---|
| 611 | TRACE("\n"); | 
|---|
| 612 | if( (ptr = (BYTE*)GlobalLock16( handle )) ) | 
|---|
| 613 | { _llseek( hFile, lpiIDE->dwImageOffset, SEEK_SET); | 
|---|
| 614 | _lread( hFile, (char*)ptr, lpiIDE->dwBytesInRes); | 
|---|
| 615 | return handle; | 
|---|
| 616 | } | 
|---|
| 617 | return 0; | 
|---|
| 618 | } | 
|---|
| 619 |  | 
|---|
| 620 | /************************************************************************* | 
|---|
| 621 | *                      ICO_GetIconDirectory | 
|---|
| 622 | * | 
|---|
| 623 | *  Read .ico file and build phony ICONDIR struct for GetIconID | 
|---|
| 624 | */ | 
|---|
| 625 | static HGLOBAL16 ICO_GetIconDirectory(HINSTANCE16 hInst, HFILE hFile, LPicoICONDIR* lplpiID ) | 
|---|
| 626 | { WORD    id[3];  /* idReserved, idType, idCount */ | 
|---|
| 627 | LPicoICONDIR  lpiID; | 
|---|
| 628 | int           i; | 
|---|
| 629 |  | 
|---|
| 630 | TRACE("\n"); | 
|---|
| 631 | _llseek( hFile, 0, SEEK_SET ); | 
|---|
| 632 | if( _lread(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0; | 
|---|
| 633 |  | 
|---|
| 634 | /* check .ICO header | 
|---|
| 635 | * | 
|---|
| 636 | * - see http://www.microsoft.com/win32dev/ui/icons.htm | 
|---|
| 637 | */ | 
|---|
| 638 |  | 
|---|
| 639 | if( id[0] || id[1] != 1 || !id[2] ) return 0; | 
|---|
| 640 |  | 
|---|
| 641 | i = id[2]*sizeof(icoICONDIRENTRY) ; | 
|---|
| 642 |  | 
|---|
| 643 | lpiID = (LPicoICONDIR)HeapAlloc( GetProcessHeap(), 0, i + sizeof(id)); | 
|---|
| 644 |  | 
|---|
| 645 | if( _lread(hFile,(char*)lpiID->idEntries,i) == i ) | 
|---|
| 646 | { HGLOBAL16 handle = DirectResAlloc16( hInst, 0x10, | 
|---|
| 647 | id[2]*sizeof(CURSORICONDIRENTRY) + sizeof(id) ); | 
|---|
| 648 | if( handle ) | 
|---|
| 649 | { CURSORICONDIR*     lpID = (CURSORICONDIR*)GlobalLock16( handle ); | 
|---|
| 650 | lpID->idReserved = lpiID->idReserved = id[0]; | 
|---|
| 651 | lpID->idType = lpiID->idType = id[1]; | 
|---|
| 652 | lpID->idCount = lpiID->idCount = id[2]; | 
|---|
| 653 | for( i=0; i < lpiID->idCount; i++ ) | 
|---|
| 654 | { memcpy((void*)(lpID->idEntries + i), | 
|---|
| 655 | (void*)(lpiID->idEntries + i), sizeof(CURSORICONDIRENTRY) - 2); | 
|---|
| 656 | lpID->idEntries[i].wResId = i; | 
|---|
| 657 | } | 
|---|
| 658 | *lplpiID = lpiID; | 
|---|
| 659 | return handle; | 
|---|
| 660 | } | 
|---|
| 661 | } | 
|---|
| 662 | /* fail */ | 
|---|
| 663 |  | 
|---|
| 664 | HeapFree( GetProcessHeap(), 0, lpiID); | 
|---|
| 665 | return 0; | 
|---|
| 666 | } | 
|---|
| 667 |  | 
|---|
| 668 | /************************************************************************* | 
|---|
| 669 | *                      InternalExtractIcon             [SHELL.39] | 
|---|
| 670 | * | 
|---|
| 671 | * This abortion is called directly by Progman | 
|---|
| 672 | */ | 
|---|
| 673 | HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16 hInstance, | 
|---|
| 674 | LPCSTR lpszExeFileName, UINT16 nIconIndex, WORD n ) | 
|---|
| 675 | {       HGLOBAL16       hRet = 0; | 
|---|
| 676 | HGLOBAL16*      RetPtr = NULL; | 
|---|
| 677 | LPBYTE          pData; | 
|---|
| 678 | OFSTRUCT        ofs; | 
|---|
| 679 | DWORD           sig; | 
|---|
| 680 | HFILE           hFile; | 
|---|
| 681 | UINT16          iconDirCount = 0,iconCount = 0; | 
|---|
| 682 | LPBYTE          peimage; | 
|---|
| 683 | HANDLE  fmapping; | 
|---|
| 684 |  | 
|---|
| 685 | TRACE("(%04x,file %s,start %d,extract %d\n", | 
|---|
| 686 | hInstance, lpszExeFileName, nIconIndex, n); | 
|---|
| 687 |  | 
|---|
| 688 | if( !n ) | 
|---|
| 689 | return 0; | 
|---|
| 690 |  | 
|---|
| 691 | hFile = OpenFile( lpszExeFileName, &ofs, OF_READ|OF_EXIST ); | 
|---|
| 692 | if(hFile == HFILE_ERROR) | 
|---|
| 693 | return 0; | 
|---|
| 694 |  | 
|---|
| 695 | hRet = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n); | 
|---|
| 696 | RetPtr = (HICON16*)GlobalLock16(hRet); | 
|---|
| 697 |  | 
|---|
| 698 | *RetPtr = (n == 0xFFFF)? 0: 1;  /* error return values */ | 
|---|
| 699 |  | 
|---|
| 700 | sig = SHELL_GetResourceTable(hFile,&pData); | 
|---|
| 701 |  | 
|---|
| 702 | if( sig==IMAGE_OS2_SIGNATURE || sig==1 ) /* .ICO file */ | 
|---|
| 703 | { HICON16        hIcon = 0; | 
|---|
| 704 | NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2); | 
|---|
| 705 | NE_NAMEINFO* pIconStorage = NULL; | 
|---|
| 706 | NE_NAMEINFO* pIconDir = NULL; | 
|---|
| 707 | LPicoICONDIR lpiID = NULL; | 
|---|
| 708 |  | 
|---|
| 709 | if( pData == (BYTE*)-1 ) | 
|---|
| 710 | { hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID);     /* check for .ICO file */ | 
|---|
| 711 | if( hIcon ) | 
|---|
| 712 | { iconDirCount = 1; iconCount = lpiID->idCount; | 
|---|
| 713 | } | 
|---|
| 714 | } | 
|---|
| 715 | else while( pTInfo->type_id && !(pIconStorage && pIconDir) ) | 
|---|
| 716 | { if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON )      /* find icon directory and icon repository */ | 
|---|
| 717 | { iconDirCount = pTInfo->count; | 
|---|
| 718 | pIconDir = ((NE_NAMEINFO*)(pTInfo + 1)); | 
|---|
| 719 | TRACE("\tfound directory - %i icon families\n", iconDirCount); | 
|---|
| 720 | } | 
|---|
| 721 | if( pTInfo->type_id == NE_RSCTYPE_ICON ) | 
|---|
| 722 | { iconCount = pTInfo->count; | 
|---|
| 723 | pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1)); | 
|---|
| 724 | TRACE("\ttotal icons - %i\n", iconCount); | 
|---|
| 725 | } | 
|---|
| 726 | pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO)); | 
|---|
| 727 | } | 
|---|
| 728 |  | 
|---|
| 729 | /* load resources and create icons */ | 
|---|
| 730 |  | 
|---|
| 731 | if( (pIconStorage && pIconDir) || lpiID ) | 
|---|
| 732 | { if( nIconIndex == (UINT16)-1 ) | 
|---|
| 733 | { RetPtr[0] = iconDirCount; | 
|---|
| 734 | } | 
|---|
| 735 | else if( nIconIndex < iconDirCount ) | 
|---|
| 736 | { UINT16   i, icon; | 
|---|
| 737 | if( n > iconDirCount - nIconIndex ) | 
|---|
| 738 | n = iconDirCount - nIconIndex; | 
|---|
| 739 |  | 
|---|
| 740 | for( i = nIconIndex; i < nIconIndex + n; i++ ) | 
|---|
| 741 | { /* .ICO files have only one icon directory */ | 
|---|
| 742 |  | 
|---|
| 743 | if( lpiID == NULL ) | 
|---|
| 744 | hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i, *(WORD*)pData ); | 
|---|
| 745 | RetPtr[i-nIconIndex] = GetIconID16( hIcon, 3 ); | 
|---|
| 746 | GlobalFree16(hIcon); | 
|---|
| 747 | } | 
|---|
| 748 |  | 
|---|
| 749 | for( icon = nIconIndex; icon < nIconIndex + n; icon++ ) | 
|---|
| 750 | { hIcon = 0; | 
|---|
| 751 | if( lpiID ) | 
|---|
| 752 | { hIcon = ICO_LoadIcon( hInstance, hFile, lpiID->idEntries + RetPtr[icon-nIconIndex]); | 
|---|
| 753 | } | 
|---|
| 754 | else | 
|---|
| 755 | { for( i = 0; i < iconCount; i++ ) | 
|---|
| 756 | { if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) ) | 
|---|
| 757 | { hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,*(WORD*)pData ); | 
|---|
| 758 | } | 
|---|
| 759 | } | 
|---|
| 760 | } | 
|---|
| 761 | if( hIcon ) | 
|---|
| 762 | { RetPtr[icon-nIconIndex] = LoadIconHandler16( hIcon, TRUE ); | 
|---|
| 763 | FarSetOwner16( RetPtr[icon-nIconIndex], GetExePtr(hInstance) ); | 
|---|
| 764 | } | 
|---|
| 765 | else | 
|---|
| 766 | { RetPtr[icon-nIconIndex] = 0; | 
|---|
| 767 | } | 
|---|
| 768 | } | 
|---|
| 769 | } | 
|---|
| 770 | } | 
|---|
| 771 | if( lpiID ) | 
|---|
| 772 | HeapFree( GetProcessHeap(), 0, lpiID); | 
|---|
| 773 | else | 
|---|
| 774 | HeapFree( GetProcessHeap(), 0, pData); | 
|---|
| 775 | } | 
|---|
| 776 |  | 
|---|
| 777 | if( sig == IMAGE_NT_SIGNATURE) | 
|---|
| 778 | { LPBYTE                idata,igdata; | 
|---|
| 779 | PIMAGE_DOS_HEADER     dheader; | 
|---|
| 780 | PIMAGE_NT_HEADERS     pe_header; | 
|---|
| 781 | PIMAGE_SECTION_HEADER pe_sections; | 
|---|
| 782 | PIMAGE_RESOURCE_DIRECTORY     rootresdir,iconresdir,icongroupresdir; | 
|---|
| 783 | PIMAGE_RESOURCE_DATA_ENTRY    idataent,igdataent; | 
|---|
| 784 | int                   i,j; | 
|---|
| 785 | PIMAGE_RESOURCE_DIRECTORY_ENTRY       xresent; | 
|---|
| 786 | CURSORICONDIR         **cids; | 
|---|
| 787 |  | 
|---|
| 788 | fmapping = CreateFileMappingA(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL); | 
|---|
| 789 | if (fmapping == 0) | 
|---|
| 790 | { /* FIXME, INVALID_HANDLE_VALUE? */ | 
|---|
| 791 | WARN("failed to create filemap.\n"); | 
|---|
| 792 | hRet = 0; | 
|---|
| 793 | goto end_2; /* failure */ | 
|---|
| 794 | } | 
|---|
| 795 | peimage = MapViewOfFile(fmapping,FILE_MAP_READ,0,0,0); | 
|---|
| 796 | if (!peimage) | 
|---|
| 797 | { WARN("failed to mmap filemap.\n"); | 
|---|
| 798 | hRet = 0; | 
|---|
| 799 | goto end_2; /* failure */ | 
|---|
| 800 | } | 
|---|
| 801 | dheader = (PIMAGE_DOS_HEADER)peimage; | 
|---|
| 802 |  | 
|---|
| 803 | /* it is a pe header, SHELL_GetResourceTable checked that */ | 
|---|
| 804 | pe_header = (PIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew); | 
|---|
| 805 |  | 
|---|
| 806 | /* probably makes problems with short PE headers... but I haven't seen | 
|---|
| 807 | * one yet... | 
|---|
| 808 | */ | 
|---|
| 809 | pe_sections = (PIMAGE_SECTION_HEADER)(((char*)pe_header)+sizeof(*pe_header)); | 
|---|
| 810 | rootresdir = NULL; | 
|---|
| 811 |  | 
|---|
| 812 | for (i=0;i<pe_header->FileHeader.NumberOfSections;i++) | 
|---|
| 813 | { if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) | 
|---|
| 814 | continue; | 
|---|
| 815 | /* FIXME: doesn't work when the resources are not in a seperate section */ | 
|---|
| 816 | if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) | 
|---|
| 817 | { rootresdir = (PIMAGE_RESOURCE_DIRECTORY)((char*)peimage+pe_sections[i].PointerToRawData); | 
|---|
| 818 | break; | 
|---|
| 819 | } | 
|---|
| 820 | } | 
|---|
| 821 |  | 
|---|
| 822 | if (!rootresdir) | 
|---|
| 823 | { WARN("haven't found section for resource directory.\n"); | 
|---|
| 824 | goto end_4; /* failure */ | 
|---|
| 825 | } | 
|---|
| 826 |  | 
|---|
| 827 | icongroupresdir = GetResDirEntryW(rootresdir,RT_GROUP_ICONW, (DWORD)rootresdir,FALSE); | 
|---|
| 828 |  | 
|---|
| 829 | if (!icongroupresdir) | 
|---|
| 830 | { WARN("No Icongroupresourcedirectory!\n"); | 
|---|
| 831 | goto end_4; /* failure */ | 
|---|
| 832 | } | 
|---|
| 833 |  | 
|---|
| 834 | iconDirCount = icongroupresdir->NumberOfNamedEntries+icongroupresdir->NumberOfIdEntries; | 
|---|
| 835 |  | 
|---|
| 836 | if( nIconIndex == (UINT16)-1 ) | 
|---|
| 837 | { RetPtr[0] = iconDirCount; | 
|---|
| 838 | goto end_3; /* success */ | 
|---|
| 839 | } | 
|---|
| 840 |  | 
|---|
| 841 | if (nIconIndex >= iconDirCount) | 
|---|
| 842 | { WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount); | 
|---|
| 843 | GlobalFree16(hRet); | 
|---|
| 844 | goto end_4; /* failure */ | 
|---|
| 845 | } | 
|---|
| 846 |  | 
|---|
| 847 | cids = (CURSORICONDIR**)HeapAlloc(GetProcessHeap(),0,n*sizeof(CURSORICONDIR*)); | 
|---|
| 848 |  | 
|---|
| 849 | /* caller just wanted the number of entries */ | 
|---|
| 850 | xresent = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(icongroupresdir+1); | 
|---|
| 851 |  | 
|---|
| 852 | /* assure we don't get too much ... */ | 
|---|
| 853 | if( n > iconDirCount - nIconIndex ) | 
|---|
| 854 | { n = iconDirCount - nIconIndex; | 
|---|
| 855 | } | 
|---|
| 856 |  | 
|---|
| 857 | /* starting from specified index ... */ | 
|---|
| 858 | xresent = xresent+nIconIndex; | 
|---|
| 859 |  | 
|---|
| 860 | for (i=0;i<n;i++,xresent++) | 
|---|
| 861 | { CURSORICONDIR       *cid; | 
|---|
| 862 | PIMAGE_RESOURCE_DIRECTORY   resdir; | 
|---|
| 863 |  | 
|---|
| 864 | /* go down this resource entry, name */ | 
|---|
| 865 | resdir = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory)); | 
|---|
| 866 |  | 
|---|
| 867 | /* default language (0) */ | 
|---|
| 868 | resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir,TRUE); | 
|---|
| 869 | igdataent = (PIMAGE_RESOURCE_DATA_ENTRY)resdir; | 
|---|
| 870 |  | 
|---|
| 871 | /* lookup address in mapped image for virtual address */ | 
|---|
| 872 | igdata = NULL; | 
|---|
| 873 |  | 
|---|
| 874 | for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) | 
|---|
| 875 | { if (igdataent->OffsetToData < pe_sections[j].VirtualAddress) | 
|---|
| 876 | continue; | 
|---|
| 877 | if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData) | 
|---|
| 878 | continue; | 
|---|
| 879 | igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData); | 
|---|
| 880 | } | 
|---|
| 881 |  | 
|---|
| 882 | if (!igdata) | 
|---|
| 883 | { WARN("no matching real address for icongroup!\n"); | 
|---|
| 884 | goto end_4;       /* failure */ | 
|---|
| 885 | } | 
|---|
| 886 | /* found */ | 
|---|
| 887 | cid = (CURSORICONDIR*)igdata; | 
|---|
| 888 | cids[i] = cid; | 
|---|
| 889 | RetPtr[i] = LookupIconIdFromDirectoryEx(igdata,TRUE,GetSystemMetrics(SM_CXICON),GetSystemMetrics(SM_CYICON),0); | 
|---|
| 890 | } | 
|---|
| 891 |  | 
|---|
| 892 | iconresdir=GetResDirEntryW(rootresdir,RT_ICONW,(DWORD)rootresdir,FALSE); | 
|---|
| 893 |  | 
|---|
| 894 | if (!iconresdir) | 
|---|
| 895 | { WARN("No Iconresourcedirectory!\n"); | 
|---|
| 896 | goto end_4; /* failure */ | 
|---|
| 897 | } | 
|---|
| 898 |  | 
|---|
| 899 | for (i=0;i<n;i++) | 
|---|
| 900 | { PIMAGE_RESOURCE_DIRECTORY   xresdir; | 
|---|
| 901 | xresdir = GetResDirEntryW(iconresdir,(LPWSTR)(DWORD)RetPtr[i],(DWORD)rootresdir,FALSE); | 
|---|
| 902 | xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir,TRUE); | 
|---|
| 903 | idataent = (PIMAGE_RESOURCE_DATA_ENTRY)xresdir; | 
|---|
| 904 | idata = NULL; | 
|---|
| 905 |  | 
|---|
| 906 | /* map virtual to address in image */ | 
|---|
| 907 | for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) | 
|---|
| 908 | { if (idataent->OffsetToData < pe_sections[j].VirtualAddress) | 
|---|
| 909 | continue; | 
|---|
| 910 | if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData) | 
|---|
| 911 | continue; | 
|---|
| 912 | idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData); | 
|---|
| 913 | } | 
|---|
| 914 | if (!idata) | 
|---|
| 915 | { WARN("no matching real address found for icondata!\n"); | 
|---|
| 916 | RetPtr[i]=0; | 
|---|
| 917 | continue; | 
|---|
| 918 | } | 
|---|
| 919 | RetPtr[i] = CreateIconFromResourceEx(idata,idataent->Size,TRUE,0x00030000,GetSystemMetrics(SM_CXICON),GetSystemMetrics(SM_CYICON),0); | 
|---|
| 920 | } | 
|---|
| 921 | goto end_3;   /* sucess */ | 
|---|
| 922 | } | 
|---|
| 923 | goto end_1;     /* return array with icon handles */ | 
|---|
| 924 |  | 
|---|
| 925 | /* cleaning up (try & catch would be nicer) */ | 
|---|
| 926 | end_4:  hRet = 0;       /* failure */ | 
|---|
| 927 | end_3:  UnmapViewOfFile(peimage);       /* success */ | 
|---|
| 928 | end_2:  CloseHandle(fmapping); | 
|---|
| 929 | end_1:  _lclose( hFile); | 
|---|
| 930 | return hRet; | 
|---|
| 931 | } | 
|---|
| 932 |  | 
|---|
| 933 | /************************************************************************* | 
|---|
| 934 | *             ExtractIcon16   (SHELL.34) | 
|---|
| 935 | */ | 
|---|
| 936 | HICON16 WINAPI ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName, | 
|---|
| 937 | UINT16 nIconIndex ) | 
|---|
| 938 | {   TRACE("\n"); | 
|---|
| 939 | return ExtractIconA( hInstance, lpszExeFileName, nIconIndex ); | 
|---|
| 940 | } | 
|---|
| 941 |  | 
|---|
| 942 | /************************************************************************* | 
|---|
| 943 | *             ExtractIconEx16   (SHELL.40) | 
|---|
| 944 | */ | 
|---|
| 945 | HICON16 WINAPI ExtractIconEx16( | 
|---|
| 946 | LPCSTR lpszFile, INT16 nIconIndex, HICON16 *phiconLarge, | 
|---|
| 947 | HICON16 *phiconSmall, UINT16 nIcons | 
|---|
| 948 | ) { | 
|---|
| 949 | HICON       *ilarge,*ismall; | 
|---|
| 950 | UINT16      ret; | 
|---|
| 951 | int         i; | 
|---|
| 952 |  | 
|---|
| 953 | if (phiconLarge) | 
|---|
| 954 | ilarge = (HICON*)HeapAlloc(GetProcessHeap(),0,nIcons*sizeof(HICON)); | 
|---|
| 955 | else | 
|---|
| 956 | ilarge = NULL; | 
|---|
| 957 | if (phiconSmall) | 
|---|
| 958 | ismall = (HICON*)HeapAlloc(GetProcessHeap(),0,nIcons*sizeof(HICON)); | 
|---|
| 959 | else | 
|---|
| 960 | ismall = NULL; | 
|---|
| 961 | ret = ExtractIconExA(lpszFile,nIconIndex,ilarge,ismall,nIcons); | 
|---|
| 962 | if (ilarge) { | 
|---|
| 963 | for (i=0;i<nIcons;i++) | 
|---|
| 964 | phiconLarge[i]=ilarge[i]; | 
|---|
| 965 | HeapFree(GetProcessHeap(),0,ilarge); | 
|---|
| 966 | } | 
|---|
| 967 | if (ismall) { | 
|---|
| 968 | for (i=0;i<nIcons;i++) | 
|---|
| 969 | phiconSmall[i]=ismall[i]; | 
|---|
| 970 | HeapFree(GetProcessHeap(),0,ismall); | 
|---|
| 971 | } | 
|---|
| 972 | return ret; | 
|---|
| 973 | } | 
|---|
| 974 |  | 
|---|
| 975 | /************************************************************************* | 
|---|
| 976 | *                              ExtractAssociatedIconA | 
|---|
| 977 | * | 
|---|
| 978 | * Return icon for given file (either from file itself or from associated | 
|---|
| 979 | * executable) and patch parameters if needed. | 
|---|
| 980 | */ | 
|---|
| 981 | HICON WINAPI ExtractAssociatedIconA(HINSTANCE hInst, LPSTR lpIconPath, LPWORD lpiIcon) | 
|---|
| 982 | {       TRACE("\n"); | 
|---|
| 983 | return ExtractAssociatedIcon16(hInst,lpIconPath,lpiIcon); | 
|---|
| 984 | } | 
|---|
| 985 |  | 
|---|
| 986 | /************************************************************************* | 
|---|
| 987 | *                              ExtractAssociatedIcon   [SHELL.36] | 
|---|
| 988 | * | 
|---|
| 989 | * Return icon for given file (either from file itself or from associated | 
|---|
| 990 | * executable) and patch parameters if needed. | 
|---|
| 991 | */ | 
|---|
| 992 | HICON16 WINAPI ExtractAssociatedIcon16(HINSTANCE16 hInst, LPSTR lpIconPath, LPWORD lpiIcon) | 
|---|
| 993 | {       HICON16 hIcon; | 
|---|
| 994 | WORD wDummyIcon = 0; | 
|---|
| 995 |  | 
|---|
| 996 | TRACE("\n"); | 
|---|
| 997 |  | 
|---|
| 998 | if(lpiIcon == NULL) | 
|---|
| 999 | lpiIcon = &wDummyIcon; | 
|---|
| 1000 |  | 
|---|
| 1001 | hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon); | 
|---|
| 1002 |  | 
|---|
| 1003 | if( hIcon < 2 ) | 
|---|
| 1004 | { if( hIcon == 1 ) /* no icons found in given file */ | 
|---|
| 1005 | { char  tempPath[0x80]; | 
|---|
| 1006 | UINT16  uRet = FindExecutable16(lpIconPath,NULL,tempPath); | 
|---|
| 1007 |  | 
|---|
| 1008 | if( uRet > 32 && tempPath[0] ) | 
|---|
| 1009 | { strcpy(lpIconPath,tempPath); | 
|---|
| 1010 | hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon); | 
|---|
| 1011 | if( hIcon > 2 ) | 
|---|
| 1012 | return hIcon; | 
|---|
| 1013 | } | 
|---|
| 1014 | else hIcon = 0; | 
|---|
| 1015 | } | 
|---|
| 1016 |  | 
|---|
| 1017 | if( hIcon == 1 ) | 
|---|
| 1018 | *lpiIcon = 2;   /* MSDOS icon - we found .exe but no icons in it */ | 
|---|
| 1019 | else | 
|---|
| 1020 | *lpiIcon = 6;   /* generic icon - found nothing */ | 
|---|
| 1021 |  | 
|---|
| 1022 | GetModuleFileName16(hInst, lpIconPath, 0x80); | 
|---|
| 1023 | hIcon = LoadIcon16( hInst, MAKEINTRESOURCE16(*lpiIcon)); | 
|---|
| 1024 | } | 
|---|
| 1025 | return hIcon; | 
|---|
| 1026 | } | 
|---|
| 1027 |  | 
|---|
| 1028 | /************************************************************************* | 
|---|
| 1029 | *                              FindEnvironmentString   [SHELL.38] | 
|---|
| 1030 | * | 
|---|
| 1031 | * Returns a pointer into the DOS environment... Ugh. | 
|---|
| 1032 | */ | 
|---|
| 1033 | LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry) | 
|---|
| 1034 | { UINT16 l; | 
|---|
| 1035 |  | 
|---|
| 1036 | TRACE("\n"); | 
|---|
| 1037 |  | 
|---|
| 1038 | l = strlen(entry); | 
|---|
| 1039 | for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 ) | 
|---|
| 1040 | { if( lstrncmpiA(lpEnv, entry, l) ) | 
|---|
| 1041 | continue; | 
|---|
| 1042 | if( !*(lpEnv+l) ) | 
|---|
| 1043 | return (lpEnv + l);                 /* empty entry */ | 
|---|
| 1044 | else if ( *(lpEnv+l)== '=' ) | 
|---|
| 1045 | return (lpEnv + l + 1); | 
|---|
| 1046 | } | 
|---|
| 1047 | return NULL; | 
|---|
| 1048 | } | 
|---|
| 1049 |  | 
|---|
| 1050 | SEGPTR WINAPI FindEnvironmentString16(LPSTR str) | 
|---|
| 1051 | { SEGPTR  spEnv; | 
|---|
| 1052 | LPSTR lpEnv,lpString; | 
|---|
| 1053 | TRACE("\n"); | 
|---|
| 1054 |  | 
|---|
| 1055 | spEnv = GetDOSEnvironment16(); | 
|---|
| 1056 |  | 
|---|
| 1057 | lpEnv = (LPSTR)PTR_SEG_TO_LIN(spEnv); | 
|---|
| 1058 | lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL; | 
|---|
| 1059 |  | 
|---|
| 1060 | if( lpString )              /*  offset should be small enough */ | 
|---|
| 1061 | return spEnv + (lpString - lpEnv); | 
|---|
| 1062 | return (SEGPTR)NULL; | 
|---|
| 1063 | } | 
|---|
| 1064 |  | 
|---|
| 1065 | /************************************************************************* | 
|---|
| 1066 | *                              DoEnvironmentSubst      [SHELL.37] | 
|---|
| 1067 | * | 
|---|
| 1068 | * Replace %KEYWORD% in the str with the value of variable KEYWORD | 
|---|
| 1069 | * from "DOS" environment. | 
|---|
| 1070 | */ | 
|---|
| 1071 | DWORD WINAPI DoEnvironmentSubst16(LPSTR str,WORD length) | 
|---|
| 1072 | { | 
|---|
| 1073 | LPSTR   lpEnv = (LPSTR)PTR_SEG_TO_LIN(GetDOSEnvironment16()); | 
|---|
| 1074 | LPSTR   lpBuffer = (LPSTR)HeapAlloc( GetProcessHeap(), 0, length); | 
|---|
| 1075 | LPSTR   lpstr = str; | 
|---|
| 1076 | LPSTR   lpbstr = lpBuffer; | 
|---|
| 1077 |  | 
|---|
| 1078 | CharToOemA(str,str); | 
|---|
| 1079 |  | 
|---|
| 1080 | TRACE("accept %s\n", str); | 
|---|
| 1081 |  | 
|---|
| 1082 | while( *lpstr && lpbstr - lpBuffer < length ) | 
|---|
| 1083 | { | 
|---|
| 1084 | LPSTR lpend = lpstr; | 
|---|
| 1085 |  | 
|---|
| 1086 | if( *lpstr == '%' ) | 
|---|
| 1087 | { | 
|---|
| 1088 | do { lpend++; } while( *lpend && *lpend != '%' ); | 
|---|
| 1089 | if( *lpend == '%' && lpend - lpstr > 1 )      /* found key */ | 
|---|
| 1090 | { | 
|---|
| 1091 | LPSTR lpKey; | 
|---|
| 1092 | *lpend = '\0'; | 
|---|
| 1093 | lpKey = SHELL_FindString(lpEnv, lpstr+1); | 
|---|
| 1094 | if( lpKey )                              /* found key value */ | 
|---|
| 1095 | { | 
|---|
| 1096 | int l = strlen(lpKey); | 
|---|
| 1097 |  | 
|---|
| 1098 | if( l > length - (lpbstr - lpBuffer) - 1 ) | 
|---|
| 1099 | { | 
|---|
| 1100 | WARN("-- Env subst aborted - string too short\n"); | 
|---|
| 1101 | *lpend = '%'; | 
|---|
| 1102 | break; | 
|---|
| 1103 | } | 
|---|
| 1104 | strcpy(lpbstr, lpKey); | 
|---|
| 1105 | lpbstr += l; | 
|---|
| 1106 | } | 
|---|
| 1107 | else break; | 
|---|
| 1108 | *lpend = '%'; | 
|---|
| 1109 | lpstr = lpend + 1; | 
|---|
| 1110 | } | 
|---|
| 1111 | else break;                                   /* back off and whine */ | 
|---|
| 1112 |  | 
|---|
| 1113 | continue; | 
|---|
| 1114 | } | 
|---|
| 1115 |  | 
|---|
| 1116 | *lpbstr++ = *lpstr++; | 
|---|
| 1117 | } | 
|---|
| 1118 |  | 
|---|
| 1119 | *lpbstr = '\0'; | 
|---|
| 1120 | if( lpstr - str == strlen(str) ) | 
|---|
| 1121 | { | 
|---|
| 1122 | strncpy(str, lpBuffer, length); | 
|---|
| 1123 | length = 1; | 
|---|
| 1124 | } | 
|---|
| 1125 | else | 
|---|
| 1126 | length = 0; | 
|---|
| 1127 |  | 
|---|
| 1128 | TRACE("-- return %s\n", str); | 
|---|
| 1129 |  | 
|---|
| 1130 | OemToCharA(str,str); | 
|---|
| 1131 | HeapFree( GetProcessHeap(), 0, lpBuffer); | 
|---|
| 1132 |  | 
|---|
| 1133 | /*  Return str length in the LOWORD | 
|---|
| 1134 | *  and 1 in HIWORD if subst was successful. | 
|---|
| 1135 | */ | 
|---|
| 1136 | return (DWORD)MAKELONG(strlen(str), length); | 
|---|
| 1137 | } | 
|---|
| 1138 |  | 
|---|
| 1139 | /************************************************************************* | 
|---|
| 1140 | *                              ShellHookProc           [SHELL.103] | 
|---|
| 1141 | * System-wide WH_SHELL hook. | 
|---|
| 1142 | */ | 
|---|
| 1143 | LRESULT WINAPI ShellHookProc16(INT16 code, WPARAM16 wParam, LPARAM lParam) | 
|---|
| 1144 | { | 
|---|
| 1145 | TRACE("%i, %04x, %08x\n", code, wParam, | 
|---|
| 1146 | (unsigned)lParam ); | 
|---|
| 1147 | if( SHELL_hHook && SHELL_hWnd ) | 
|---|
| 1148 | { | 
|---|
| 1149 | UINT16  uMsg = 0; | 
|---|
| 1150 | switch( code ) | 
|---|
| 1151 | { | 
|---|
| 1152 | case HSHELL_WINDOWCREATED:          uMsg = uMsgWndCreated;   break; | 
|---|
| 1153 | case HSHELL_WINDOWDESTROYED:        uMsg = uMsgWndDestroyed; break; | 
|---|
| 1154 | case HSHELL_ACTIVATESHELLWINDOW:    uMsg = uMsgShellActivate; | 
|---|
| 1155 | } | 
|---|
| 1156 | PostMessage16( SHELL_hWnd, uMsg, wParam, 0 ); | 
|---|
| 1157 | } | 
|---|
| 1158 | return CallNextHookEx16( WH_SHELL, code, wParam, lParam ); | 
|---|
| 1159 | } | 
|---|
| 1160 |  | 
|---|
| 1161 | /************************************************************************* | 
|---|
| 1162 | *                              RegisterShellHook       [SHELL.102] | 
|---|
| 1163 | */ | 
|---|
| 1164 | BOOL WINAPI RegisterShellHook16(HWND16 hWnd, UINT16 uAction) | 
|---|
| 1165 | { | 
|---|
| 1166 | TRACE("%04x [%u]\n", hWnd, uAction ); | 
|---|
| 1167 |  | 
|---|
| 1168 | switch( uAction ) | 
|---|
| 1169 | { | 
|---|
| 1170 | case 2:  /* register hWnd as a shell window */ | 
|---|
| 1171 | if( !SHELL_hHook ) | 
|---|
| 1172 | { | 
|---|
| 1173 | HMODULE16 hShell = GetModuleHandle16( "SHELL" ); | 
|---|
| 1174 | HOOKPROC16 hookProc = (HOOKPROC16)NE_GetEntryPoint( hShell, 103 ); | 
|---|
| 1175 | SHELL_hHook = SetWindowsHookEx16( WH_SHELL, hookProc, hShell, 0 ); | 
|---|
| 1176 | if ( SHELL_hHook ) | 
|---|
| 1177 | { | 
|---|
| 1178 | uMsgWndCreated = RegisterWindowMessageA( lpstrMsgWndCreated ); | 
|---|
| 1179 | uMsgWndDestroyed = RegisterWindowMessageA( lpstrMsgWndDestroyed ); | 
|---|
| 1180 | uMsgShellActivate = RegisterWindowMessageA( lpstrMsgShellActivate ); | 
|---|
| 1181 | } | 
|---|
| 1182 | else | 
|---|
| 1183 | WARN("-- unable to install ShellHookProc()!\n"); | 
|---|
| 1184 | } | 
|---|
| 1185 |  | 
|---|
| 1186 | if ( SHELL_hHook ) | 
|---|
| 1187 | return ((SHELL_hWnd = hWnd) != 0); | 
|---|
| 1188 | break; | 
|---|
| 1189 |  | 
|---|
| 1190 | default: | 
|---|
| 1191 | WARN("-- unknown code %i\n", uAction ); | 
|---|
| 1192 | SHELL_hWnd = 0; /* just in case */ | 
|---|
| 1193 | } | 
|---|
| 1194 | return FALSE; | 
|---|
| 1195 | } | 
|---|
| 1196 | #endif | 
|---|