/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
mapembed.c
Abstract:
This module contains the functions that perform the mapping
between the "embedding" section of win.ini, and the subkeys
of HKEY_CLASSES_ROOT.
This mapping is a hack implemented on Win3.1, that must also
exist on NT.
It is implemnted in the WOW layer, since only some win16 apps
that read or write to the "embedding" section ( WinWord and
MsMail) depend on it.
Author:
Jaime F. Sasson (jaimes) 25-Nov-1992
--*/
#include "precomp.h"
#pragma hdrstop
MODNAME(mapembed.c);
#define WININITIMEOUT 2000
#define BUFFER_SIZE 128
#define EMPTY_STRING ""
DWORD _LastTimeUpdated = 0;
BOOL
IsWinIniHelper(
IN LPSTR FileName
)
/*++
Routine Description:
Determine if the name passed as argument refers to the file win.ini.
Used by IS_WIN_INI macro, which assures the argument is non-null and
deals with exact match of "win.ini".
Arguments:
FileName - File name to be examined.
Return Value:
BOOL - Returns TRUE if 'Name' refers to win.ini.
Otherwise, returns FALSE.
--*/
{
CHAR BufferForFullPath[MAX_PATH];
PSTR PointerToName;
DWORD SizeOfFullPath;
BOOL Result;
#ifdef DEBUG
//
// Filename argument must already be lowercase. Be sure.
//
{
char Lowercase[MAX_PATH];
WOW32ASSERT(strlen(FileName) < MAX_PATH-1);
strcpy(Lowercase, FileName);
_strlwr(Lowercase);
WOW32ASSERT(!strcmp(FileName, Lowercase));
}
#endif
if (!strcmp(FileName, szWinDotIni)) {
Result = TRUE;
goto Done;
}
SizeOfFullPath = GetFullPathName( FileName,
sizeof BufferForFullPath,
BufferForFullPath,
&PointerToName );
if (SizeOfFullPath == 0) {
Result = FALSE;
goto Done;
}
WOW32ASSERT( (SizeOfFullPath + 1) <= sizeof BufferForFullPath );
WOW32ASSERTMSG(pszWinIniFullPath && pszWinIniFullPath[0],
"WOW32 ERROR pszWinIniFullPath not initialized.\n");
Result = !_stricmp( pszWinIniFullPath, BufferForFullPath );
Done:
return Result;
}
VOID
UpdateEmbeddingAllKeys(
)
/*++
Routine Description:
Update the "embedding" section of win.ini based on the information
stored on the subkeys of HKEY_CLASSES_ROOT.
Arguments:
None.
Return Value:
None.
--*/
{
LONG iClass;
CHAR szClass[MAX_PATH + 1];
LONG Status;
for (iClass = 0;
(Status = RegEnumKey(HKEY_CLASSES_ROOT,iClass,szClass,sizeof( szClass ))) != ERROR_NO_MORE_ITEMS;
iClass++)
{
if( Status == ERROR_SUCCESS ) {
UpdateEmbeddingKey( szClass );
}
}
}
VOID
UpdateEmbeddingKey(
IN LPSTR KeyName
)
/*++
Routine Description:
Update one key of the "embedding" section of win.ini based on the
information stored on the correspondent subkey of HKEY_CLASSES_ROOT.
The code below is an improved version of the function
"UpdateWinIni" extracted from Win 3.1 (shell\library\dbf.c).
Arguments:
KeyName - Name of the key to be updated.
Return Value:
None.
--*/
{
LONG Status;
HKEY Key;
PSTR szClass;
LPSTR szClassName;
CHAR BufferForClassName[BUFFER_SIZE];
// char szClassName[60];
LPSTR szServer;
CHAR BufferForServer[BUFFER_SIZE];
// char szServer[64];
LPSTR szLine;
CHAR BufferForLine[2*BUFFER_SIZE];
// char szLine[128];
char szOldLine[2*BUFFER_SIZE];
// char szOldLine[128];
LPSTR lpDesc, lpForms;
int nCommas;
LONG cchClassNameSize;
LONG cchServerSize;
LONG cchLineSize;
if( KeyName == NULL ) {
return;
}
szClass = KeyName;
Key = NULL;
szClassName = BufferForClassName;
cchClassNameSize = sizeof( BufferForClassName );
szServer = BufferForServer;
cchServerSize = sizeof( BufferForServer );
szLine = BufferForLine;
if( RegOpenKey( HKEY_CLASSES_ROOT, szClass, &Key ) != ERROR_SUCCESS )
goto NukeClass;
Status = RegQueryValue(Key,NULL,szClassName,&cchClassNameSize);
if( ( Status != ERROR_SUCCESS ) &&
( Status != ERROR_MORE_DATA ) )
goto NukeClass;
if( Status == ERROR_MORE_DATA ) {
cchClassNameSize++;
szClassName = ( PSTR )malloc_w( cchClassNameSize );
if( szClassName == NULL )
goto NukeClass;
Status = RegQueryValue(Key,NULL,szClassName,&cchClassNameSize);
if( Status != ERROR_SUCCESS )
goto NukeClass;
}
if (!*szClassName)
goto NukeClass;
Status = RegQueryValue(Key,szServerKey,szServer,&cchServerSize);
if( ( Status != ERROR_SUCCESS ) &&
( Status != ERROR_MORE_DATA ) )
goto NukeClass;
if( Status == ERROR_MORE_DATA ) {
cchServerSize++;
szServer = malloc_w( cchServerSize );
if( szServer == NULL )
goto NukeClass;
Status = RegQueryValue(Key,szServerKey,szServer,&cchServerSize);
if( Status != ERROR_SUCCESS )
goto NukeClass;
}
if (!*szServer)
goto NukeClass;
if (GetProfileString(szEmbedding, szClass, EMPTY_STRING,
szOldLine, sizeof(szOldLine)))
{
for (lpForms=szOldLine, nCommas=0; ; lpForms=AnsiNext(lpForms))
{
while (*lpForms == ',')
{
*lpForms++ = '\0';
if (++nCommas == 3)
goto FoundForms;
}
if (!*lpForms)
goto DoDefaults;
}
FoundForms:
lpDesc = szOldLine;
}
else
{
DoDefaults:
lpDesc = szClassName;
lpForms = szPicture;
}
// we have a class, a classname, and a server, so its an le class
cchLineSize = strlen( lpDesc ) +
strlen( szClassName ) +
strlen( szServer ) +
strlen( lpForms ) +
3 +
1;
if( cchLineSize > sizeof( BufferForLine ) ) {
szLine = malloc_w( cchLineSize );
if( szLine == NULL )
goto NukeClass;
}
wsprintf(szLine, "%s,%s,%s,%s",
lpDesc, (LPSTR)szClassName, (LPSTR)szServer, lpForms);
WriteProfileString(szEmbedding, szClass, szLine);
if( Key != NULL ) {
RegCloseKey( Key );
}
if( szClassName != BufferForClassName ) {
free_w( szClassName );
}
if( szServer != BufferForServer ) {
free_w( szServer );
}
if( szLine != BufferForLine ) {
free_w( szLine );
}
return;
NukeClass:
/*
Don't nuke the class because someone else may use it!
*/
if( Key != NULL ) {
RegCloseKey( Key );
}
if( szClassName != BufferForClassName ) {
free_w( szClassName );
}
if( szServer != BufferForServer ) {
free_w( szServer );
}
if( szLine != BufferForLine ) {
free_w( szLine );
}
WriteProfileString(szEmbedding,szClass,NULL);
}
VOID
UpdateClassesRootSubKey(
IN LPSTR KeyName,
IN LPSTR Value
)
/*++
Routine Description:
Update a subkeys of HKEY_CLASSES_ROOT, based on the corresponding
key in the "embedding" section of win.ini.
The code below is an improved version of the function
"UpdateFromWinIni" extracted from Win 3.1 (shell\library\dbf.c).
Arguments:
KeyName - Name of the subkey to be updated
Value - The value associated to the key, that was already written
to the "embedding" section of win.ini.
Return Value:
None.
--*/
{
LPSTR szLine;
LPSTR lpClass,lpServer,lpClassName;
LPSTR lpT;
HKEY key = NULL;
HKEY key1 = NULL;
if( ( KeyName == NULL ) || ( Value == NULL ) ) {
return;
}
lpClass = KeyName;
szLine = Value;
if (!(lpClassName=strchr(szLine, ',')))
return;
// get the server name and null terminate the class name
if (!(lpServer=strchr(++lpClassName, ','))) {
return;
}
*lpServer++ = '\0';
// null terminate the server
if (!(lpT=strchr(lpServer, ','))) {
return;
}
*lpT++ = '\0';
// make sure the classname is nonblank
while (*lpClassName == ' ')
lpClassName++;
if (!*lpClassName)
return;
// make sure the server name is nonblank
while (*lpServer == ' ')
lpServer++;
if (!*lpServer)
return;
// we now have a valid entry
key = NULL;
if( ( RegCreateKey( HKEY_CLASSES_ROOT, lpClass, &key ) != ERROR_SUCCESS ) ||
( RegSetValue( key, NULL, REG_SZ, lpClassName, strlen( lpClassName ) ) != ERROR_SUCCESS ) ) {
if( key != NULL ) {
RegCloseKey( key );
}
return;
}
if( ( RegCreateKey( key, szServerKey, &key1 ) != ERROR_SUCCESS ) ||
( RegSetValue( key1, NULL, REG_SZ, lpServer, strlen( lpServer ) ) != ERROR_SUCCESS ) ) {
if( key != NULL ) {
RegCloseKey( key );
}
if( key1 != NULL ) {
RegCloseKey( key1 );
}
return;
}
RegCloseKey( key );
RegCloseKey( key1 );
}
VOID
SetLastTimeUpdated(
)
/*++
Routine Description:
Set the variable that contains the information of when the "embedding"
section of win.ini was last updated.
Arguments:
None.
Return Value:
None.
--*/
{
_LastTimeUpdated = GetTickCount();
}
BOOL
WasSectionRecentlyUpdated(
)
/*++
Routine Description:
Inform the caller whether the "embedding" section of win.ini
was recently updated ( less than 2 seconds ).
Arguments:
None.
Return Value:
BOOLEAN - Returns TRUE if the "embedding" section was updated less than
2 seconds ago.
--*/
{
DWORD Now;
Now = GetTickCount();
return( ( ( Now - _LastTimeUpdated ) < WININITIMEOUT ) ? TRUE : FALSE );
}