winx.c

C:\home\SVGCats_src\src\winx.c

[大目次 | 目次 | 関数]

大目次

目次

関数一覧


   1|/**************************************************************************
   2|*   1. <<< Windows API (WinX) >>> 
   3|*【参考】
   4|*・http://www.kt.rim.or.jp/~yuta/prog/win32/
   5|*【API index】
   6|*・GetSystemDirectory
   7|***************************************************************************/
   8|
   9|#ifdef  UNDER_CE
  10| #error  not support for WinCE
  11|#endif
  12|
  13|#include  <windows.h>
  14|// #pragma hdrstop
  15|#ifdef  USES_MXP_AUTOINC
  16| #include  "winx.ah"  /* Auto include header, Look at mixer-... folder */
  17|#else
  18| #include  <all.h>
  19|#endif
  20|
  21|/*#define  WINX_ENABLE_DEBUG_MODE*/
  22|
  23|#include  <winreg.h>   /* レジストリ関係 */
  24|#include  <ddeml.h>    /* DDE 通信関係 */
  25|#include  <direct.h>
  26|#include  <limits.h>
  27|#include  <stdio.h>
  28|
  29|extern char   WinX_dde_command[];
  30|extern char   WinX_dde_service[];
  31|extern char   WinX_dde_topic[];
  32|
  33|
  34| 
  35|/*------------------------------------------------------------------------*/
  36|/*  2. <<<< サブルーチン >>>> */ 
  37|/*------------------------------------------------------------------------*/
  38| 
  39|/**************************************************************************
  40|*  2-1. <<< [WinX_error] エラーを発生させる(GetLastError 使用) >>> 
  41|***************************************************************************/
  42|void   WinX_error(void)
  43|{
  44|  static char  msg[256];
  45|  int  errcode = GetLastError();
  46|
  47|  FormatMessage(
  48|    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  49|    NULL, errcode,
  50|    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // デフォルト言語
  51|    (LPTSTR) msg, sizeof(msg), NULL );
  52|  error2_4( WinX_Err_API_Error, "API Error : %s, allcode = %08X (Facility=%d, Code=%d)", \
  53|    msg, (errcode), ((errcode) & 0x0FFF0000) >> 16, ((errcode) & 0x0000FFFF) );
  54|}
  55|
  56| 
  57|/**************************************************************************
  58|*  2-2. <<< [WinX_error2] エラーを発生させる(返り値使用) >>> 
  59|***************************************************************************/
  60|void   WinX_error2( LONG code )
  61|{
  62|  static char  msg[256];
  63|
  64|  FormatMessage(
  65|    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  66|    NULL, code,
  67|    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // デフォルト言語
  68|    (LPTSTR) msg, sizeof(msg), NULL );
  69|  error2_1( WinX_Err_API_Error, "API Error : %s", msg );
  70|}
  71|
  72| 
  73|/**************************************************************************
  74|*  2-3. <<< [WinX_throw_imp] API のエラーコード例外を投げる >>> 
  75|*【引数】
  76|*  ・int  errcode   エラーコード;
  77|*【補足】
  78|*・エラーコードの内容は、winerror.h(C:\Program Files\Microsoft Visual Studio\
  79|*  VC98\Include\WINERROR.H) に書いてあります。
  80|*  ただし、エラーコードはビットフィールドによって複数の情報が入っていることに
  81|*  注意してください。
  82|***************************************************************************/
  83|#ifdef  USES_EXCEPT2
  84|void  WinX_throw_imp( int errcode, char* file, int line )
  85|{
  86|  throw( Except2_Str_newExcept2_f( "WinX: API Error in %s:%d\n"
  87|    "allcode = %08X ( Sev=%d, Facility=%d, Code=%d)",
  88|    file, line, errcode, (errcode & 0xC0000000) >> 30,
  89|    (errcode & 0x0FFF0000) >> 16, (errcode & 0x0000FFFF) ) );
  90|}
  91|#else
  92|void  WinX_throw_imp( int errcode, char* file, int line )
  93|{
  94|  static char  msg[256];
  95|
  96|  FormatMessage(
  97|    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  98|    NULL, errcode,
  99|    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // デフォルト言語
 100|    (LPTSTR) msg, sizeof(msg), NULL );
 101|  sprintf( strchr( msg, '\0' ), ", allcode = %08X (Facility=%d, Code=%d)",
 102|    (errcode), ((errcode) & 0x0FFF0000) >> 16, ((errcode) & 0x0000FFFF) );
 103|  error2_3( WinX_Err_API_Error, "API Error : %s in %s(%d)", \
 104|    msg, file, line );
 105|}
 106|#endif  /* USES_EXCEPT2 */
 107| 
 108|/**************************************************************************
 109|*  2-4. <<< [WinX_throwDde_imp] DDE のエラーコード例外を投げる >>> 
 110|*【引数】
 111|*  ・DWORD  dde;    DdeInitialize の第1引数と同じ
 112|***************************************************************************/
 113|void  WinX_throwDde_imp( DWORD dde, char* file, int line )
 114|{
 115|  char*  errstr;
 116|
 117|  switch ( DdeGetLastError( dde ) ) {
 118|    case DMLERR_ADVACKTIMEOUT:
 119|      errstr = "DMLERR_ADVACKTIMEOUT";  break;
 120|    case DMLERR_BUSY:
 121|      errstr = "DMLERR_BUSY";  break;
 122|    case DMLERR_DATAACKTIMEOUT:
 123|      errstr = "DMLERR_DATAACKTIMEOUT";  break;
 124|    case DMLERR_DLL_NOT_INITIALIZED:
 125|      errstr = "DMLERR_NOT_INITIALIZED";  break;
 126|    case DMLERR_DLL_USAGE:
 127|      errstr = "DMLERR_DLL_USAGE";  break;
 128|    case DMLERR_EXECACKTIMEOUT:
 129|      errstr = "DMLERR_EXECACKTIMEOUT";  break;
 130|    case DMLERR_INVALIDPARAMETER:
 131|      errstr = "DMLERR_INVALIDPARAMETER";  break;
 132|    case DMLERR_LOW_MEMORY:
 133|      errstr = "DMLERR_LOW_MEMORY";  break;
 134|    case DMLERR_MEMORY_ERROR:
 135|      errstr = "DMLERR_MEMORY_ERROR";  break;
 136|    case DMLERR_NO_CONV_ESTABLISHED:
 137|      errstr = "DMLERR_NO_CONV_ESTABLISHED";  break;
 138|    case DMLERR_NOTPROCESSED:
 139|      errstr = "DMLERR_NOTPROCESSED";  break;
 140|    case DMLERR_POKEACKTIMEOUT:
 141|      errstr = "DMLERR_POKEACKTIMEOUT";  break;
 142|    case DMLERR_POSTMSG_FAILED:
 143|      errstr = "DMLERR_POSTMSG_FAILED";  break;
 144|    case DMLERR_REENTRANCY:
 145|      errstr = "DMLERR_REENTRANCY";  break;
 146|    case DMLERR_SERVER_DIED:
 147|      errstr = "DMLERR_SERVER_DIED";  break;
 148|    case DMLERR_SYS_ERROR:
 149|      errstr = "DMLERR_SYS_ERROR";  break;
 150|    case DMLERR_UNADVACKTIMEOUT:
 151|      errstr = "DMLERR_UNADVACKTIMEOUT";  break;
 152|    case DMLERR_UNFOUND_QUEUE_ID:
 153|      errstr = "DMLERR_UNFOUND_QUEUE_ID";  break;
 154|    default:
 155|      errstr = "unknown";  break;
 156|  }
 157|
 158|  #ifdef  USES_EXCEPT2
 159|  throw( Except2_Str_newExcept2_f(
 160|    "WinX: DDE Error : %s in %s:%d",
 161|    errstr, file, line ) );
 162|  #else
 163|    error2_5( WinX_Err_DdeError, "WinX: DDE Error command=%s, service=%s, topic=%s: in %s:%d",
 164|      WinX_dde_command, WinX_dde_service, WinX_dde_topic, errstr, line );
 165|  #endif  /* USES_EXCEPT2 */
 166|}
 167|
 168| 
 169|/*------------------------------------------------------------------------*/
 170|/*  3. <<<< ◆ レジストリ関係 >>>> */ 
 171|/*------------------------------------------------------------------------*/
 172|
 173|
 174| 
 175|/**************************************************************************
 176|  3-1. <<< [WinX_getReg] レジストリの値(任意の型)を取得する >>> 
 177|【引数】
 178|  ・HKEY   baseKey;    基準キー(HKEY_CLASSES_ROOT など、サブキーでも可)
 179|  ・char*  path;       基準キーからのパス
 180|  ・bool   bDef;       path は(標準または規定)のデータかどうか
 181|  ・WinX_RegData* data;   レジストリ・データ
 182|【補足】
 183|・キーが HKEY_CLASSES_ROOT\Display\Settings の場合、
 184|  baseKey == HKEY_CLASSES_ROOT, path == "Display\\Settings" を指定します。
 185|・path に指定したキーが無いときは、例外を発生します。
 186|・キーは、レジストリエディタの左半分のツリーに表示されるフォルダアイコン、
 187|  データは、レジストリエディタの右半分に表示されるアイコンに相当します。
 188|***************************************************************************/
 189|void  WinX_getReg( HKEY baseKey, const char* path, bool bDef, WinX_RegData* data )
 190|{
 191|  LONG   ret;
 192|  HKEY   key;
 193|  DWORD  size = data->maxSize;
 194|  const char*  keyPath;
 195|  char*  dataName;
 196|  char   s[512];
 197|
 198|  ERRORS_FUNC_START( WinX_getReg );
 199|
 200|  /* keyPath と namePath を設定する */
 201|  if ( bDef ) {
 202|    keyPath = path;
 203|    dataName = NULL;
 204|  }
 205|  else {
 206|    if ( strlen( path ) >= sizeof( s ) )
 207|      error2_1( WinX_Err_TooLongPath, "レジストリのパスが長すぎます(%s)", path );
 208|    strcpy( s, path );
 209|    keyPath = s;
 210|    dataName = StrX_RSearchC2( s, '\\' ) + 1;
 211|    *(dataName - 1) = '\0';
 212|  }
 213|
 214|  /* レジストリ・データを取得する */
 215|  ret = RegOpenKeyEx( baseKey, keyPath, 0L, KEY_READ, &key );
 216|  if ( ret != ERROR_SUCCESS ) {
 217|    if ( ret == 2 ) {
 218|      error2_1( WinX_Err_NoRegKey, "レジストリのキー「%s」が見つかりません。",
 219|        path );
 220|    }
 221|    else
 222|      WinX_throw( ret );
 223|  }
 224|
 225|  ret = RegQueryValueEx( key, dataName, NULL, &data->type, data->data, &size );
 226|  if ( ret != ERROR_SUCCESS ) {
 227|    RegCloseKey( key );
 228|    if ( ret == ERROR_FILE_NOT_FOUND || ret == ERROR_MORE_DATA ) {
 229|      if ( dataName == NULL ) {
 230|        error2_1( WinX_Err_NoRegData, "レジストリのキー「%s」のデータ(標準)が見つかりません。",
 231|          path );
 232|      }
 233|      else {
 234|        error2_2( WinX_Err_NoRegData, "レジストリのキー「%s」のデータ「%s」が見つかりません。",
 235|          path, dataName );
 236|      }
 237|    }
 238|    else
 239|    WinX_throw( ret );
 240|  }
 241|  data->size = size;
 242|
 243|  ret = RegCloseKey( key );
 244|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
 245|
 246|  ERRORS_FUNC_END( WinX_getReg );
 247|}
 248| 
 249|/**************************************************************************
 250|  3-2. <<< [WinX_setReg] レジストリの値(任意の型)を設定する >>> 
 251|【引数】
 252|  ・HKEY   baseKey;    基準キー(HKEY_CLASSES_ROOT など、サブキーでも可)
 253|  ・char*  path;       基準キーからのパス
 254|  ・bool   bDef;       path は(標準または規定)のデータかどうか
 255|  ・WinX_RegData* data;   レジストリ・データ
 256|【補足】
 257|・キーが HKEY_CLASSES_ROOT\Display\Settings の場合、
 258|  baseKey == HKEY_CLASSES_ROOT, path == "Display\\Settings" を指定します。
 259|・path のキーやデータが存在しないときは、新しく作成します。
 260|・キーは、レジストリエディタの左半分のツリーに表示されるフォルダアイコン、
 261|  データは、レジストリエディタの右半分に表示されるアイコンに相当します。
 262|***************************************************************************/
 263|void  WinX_setReg( HKEY baseKey, const char* path, bool bDef, WinX_RegData* data )
 264|{
 265|  LONG  ret;
 266|  HKEY  key;
 267|  const char*  keyPath;
 268|  char*  dataName;
 269|  char   s[512];
 270|  DWORD  dwDisp;
 271|
 272|  ERRORS_FUNC_START( WinX_setReg );
 273|
 274|  /* keyPath と namePath を設定する */
 275|  if ( bDef ) {
 276|    keyPath = path;
 277|    dataName = NULL;
 278|  }
 279|  else {
 280|    if ( strlen( path ) >= sizeof( s ) )
 281|      error2_1( WinX_Err_TooLongPath, "レジストリのパスが長すぎます(%s)", path );
 282|    strcpy( s, path );
 283|    keyPath = s;
 284|    dataName = StrX_RSearchC2( s, '\\' ) + 1;
 285|    *(dataName - 1) = '\0';
 286|  }
 287|
 288|  /* レジストリ・データを設定する */
 289|  ret = RegCreateKeyEx( baseKey, keyPath, 0, 0,
 290|     REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
 291|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
 292|
 293|  ret = RegSetValueEx( key, dataName, 0,
 294|    data->type, data->data, data->size );
 295|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
 296|
 297|  ret = RegCloseKey( key );
 298|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
 299|
 300|  ERRORS_FUNC_END( WinX_setReg );
 301|}
 302| 
 303|/**************************************************************************
 304|  3-3. <<< [WinX_delReg] レジストリのキーまたはデータを削除する >>> 
 305|【引数】
 306|  ・HKEY   baseKey;    基準キー(HKEY_CLASSES_ROOT など、サブキーでも可)
 307|  ・char*  path;       基準キーからのパス
 308|  ・bool   bKey;       path はキーかどうか
 309|【補足】
 310|・サブ・キーがあったときは、例外が発生します。
 311|***************************************************************************/
 312|void  WinX_delReg( HKEY baseKey, const char* path, bool bKey )
 313|{
 314|  LONG  ret;
 315|
 316|  ERRORS_FUNC_START( WinX_delReg );
 317|
 318|  if ( bKey && StrX_strchr2( path, '\\' ) == NULL ) {
 319|    ret = RegDeleteKey( baseKey, path );
 320|    if ( (ret & 0xFFFF) != ERROR_FILE_NOT_FOUND && ret != ERROR_SUCCESS )
 321|      WinX_throw( ret );
 322|  }
 323|  else {
 324|    HKEY  key;
 325|    char  path2[512];
 326|    char  name2[512];
 327|
 328|    StrX_cpyFolder( path2, path );
 329|    StrX_cpyFName( name2, path );
 330|    ret = RegOpenKeyEx( baseKey, path2, 0L, KEY_WRITE, &key );
 331|    if ( (ret & 0xFFFF) != ERROR_FILE_NOT_FOUND ) {
 332|      if ( ret != ERROR_SUCCESS )
 333|        WinX_throw( ret );
 334|
 335|      if ( bKey )
 336|        ret = RegDeleteKey( key, name2 );
 337|      else
 338|        ret = RegDeleteValue( key, name2 );
 339|      if ( (ret & 0xFFFF) != ERROR_FILE_NOT_FOUND && ret != ERROR_SUCCESS )
 340|        WinX_throw( ret );
 341|
 342|      ret = RegCloseKey( key );
 343|      if ( ret != ERROR_SUCCESS )
 344|        WinX_throw( ret );
 345|    }
 346|  }
 347|
 348|  ERRORS_FUNC_END( WinX_delReg );
 349|}
 350| 
 351|/**************************************************************************
 352|  3-4. <<< [WinX_delRegIfNoSub] サブキーが無ければ削除する >>> 
 353|【引数】
 354|  ・HKEY   baseKey;    基準キー(HKEY_CLASSES_ROOT など、サブキーでも可)
 355|  ・char*  path;       削除するキー、基準キーからのパス
 356|***************************************************************************/
 357|void  WinX_delRegIfNoSub( HKEY baseKey, const char* path )
 358|{
 359|  LONG  ret;
 360|  HKEY  key;
 361|  char  path2[512];
 362|  char  name1[512];
 363|  char  name2[512];
 364|  int   size;
 365|
 366|  ERRORS_FUNC_START( WinX_delRegIfNoSub );
 367|
 368|  ret = RegOpenKeyEx( baseKey, path, 0L, KEY_ALL_ACCESS, &key );
 369|  if ( (ret & 0xFFFF) != ERROR_FILE_NOT_FOUND ) {
 370|    if ( ret != ERROR_SUCCESS )
 371|      WinX_throw( ret );
 372|
 373|    size = sizeof(name1);
 374|    ret = RegEnumKeyEx( key, 0, name1, &size, NULL, NULL, NULL, NULL );
 375|    if ( ret != ERROR_SUCCESS ) {
 376|
 377|      if ( StrX_strchr2( path, '\\' ) == NULL ) {
 378|        ret = RegDeleteKey( baseKey, path );
 379|        if ( ret != ERROR_SUCCESS )
 380|          WinX_throw( ret );
 381|      }
 382|      else {
 383|        ret = RegCloseKey( key );
 384|        if ( ret != ERROR_SUCCESS )
 385|          WinX_throw( ret );
 386|
 387|        StrX_cpyFolder( path2, path );
 388|        StrX_cpyFName( name2, path );
 389|        ret = RegOpenKeyEx( baseKey, path2, 0L, KEY_ALL_ACCESS, &key );
 390|        if ( ret != ERROR_SUCCESS )
 391|          WinX_throw( ret );
 392|
 393|        ret = RegDeleteKey( key, name2 );
 394|        if ( ret != ERROR_SUCCESS ) {
 395|          error2_4( WinX_Err_AccessDenied, "%s(%s,%s) を削除できません(%d)",
 396|            name2, path2, name1, ret );  /* レジストリを確認(保存) */
 397|        }
 398|      }
 399|    }
 400|    ret = RegCloseKey( key );
 401|    if ( ret != ERROR_SUCCESS )
 402|      WinX_throw( ret );
 403|  }
 404|
 405|  ERRORS_FUNC_END( WinX_delRegIfNoSub );
 406|}
 407| 
 408|/**************************************************************************
 409|  3-5. <<< [WinX_isExistReg] レジストリのキーまたはデータが存在するかどうかを返す >>> 
 410|【引数】
 411|  ・HKEY   baseKey;    基準キー(HKEY_CLASSES_ROOT など、サブキーでも可)
 412|  ・char*  path;       基準キーからのパス
 413|  ・bool   bKey;       path はキーかどうか
 414|  ・bool   bKeyOrData;    path が、キーとデータの違いがあっても true を返すかどうか
 415|***************************************************************************/
 416|bool  WinX_isExistReg( HKEY baseKey, const char* path, bool bKey, bool bKeyOrData )
 417|{
 418|  HKEY  key;
 419|  LONG  ret;
 420|
 421|  ERRORS_FUNC_START( WinX_isExistReg );
 422|
 423|  /* キーが存在するかどうかを調べる */
 424|  if ( bKey || bKeyOrData ) {
 425|    ret = RegOpenKeyEx( baseKey, path, 0L, KEY_QUERY_VALUE, &key );
 426|    if ( ret == ERROR_SUCCESS ) {
 427|      RegCloseKey( key );
 428|      ERRORS_FUNC_END( WinX_isExistReg );
 429|      return  true;
 430|    }
 431|  }
 432|
 433|  /* データが存在するかどうかを調べる */
 434|  if ( ! bKey || bKeyOrData ) {
 435|    char   s[512];
 436|
 437|    StrX_cpyFolder( s, path );
 438|    ret = RegOpenKeyEx( baseKey, s, 0L, KEY_READ, &key );
 439|    if ( ret != ERROR_SUCCESS )  return  false;
 440|
 441|    ret = RegQueryValueEx( key, StrX_refFName( path ), NULL, NULL, NULL, 0 );
 442|
 443|    RegCloseKey( key );
 444|
 445|    ERRORS_FUNC_END( WinX_isExistReg );
 446|    return  ( ret == ERROR_SUCCESS );
 447|  }
 448|
 449|  ERRORS_FUNC_END( WinX_isExistReg );
 450|  return  false;
 451|}
 452| 
 453|/**************************************************************************
 454|  3-6. <<< [WinX_getReg_s] レジストリの値(文字列)を取得する >>> 
 455|【引数】
 456|  ・HKEY   baseKey;    基準キー(HKEY_CLASSES_ROOT など、サブキーでも可)
 457|  ・char*  subKey;     キーの残りの文字列
 458|  ・char*  name;       データの名前の文字列(標準の場合は NULL)
 459|  ・char*  var;        データ(文字列)を格納するアドレス
 460|  ・int    var_size;   var のメモリサイズ
 461|【補足】
 462|・WinX_getReg の説明を参照。
 463|***************************************************************************/
 464|char*  WinX_getReg_s( HKEY baseKey, const char* subKeyPath,
 465|  const char* name, char* var, int var_size )
 466|{
 467|  LONG   ret;
 468|  HKEY   key;
 469|  DWORD  type;
 470|  DWORD  size = var_size;
 471|
 472|  ERRORS_FUNC_START( WinX_getReg_s );
 473|
 474|  ret = RegOpenKeyEx( baseKey, subKeyPath, 0L, KEY_READ, &key );
 475|  if ( ret != ERROR_SUCCESS ) {
 476|    if ( ret == 2 ) {
 477|      error2_1( WinX_Err_NoRegKey, "レジストリのキー「%s」が見つかりません。",
 478|        subKeyPath );
 479|    }
 480|    else
 481|      WinX_throw( ret );
 482|  }
 483|
 484|  ret = RegQueryValueEx( key, name, NULL, &type, var, &size );
 485|  if ( ret != ERROR_SUCCESS ) {
 486|    RegCloseKey( key );
 487|    if ( ret == 2 ) {
 488|      error2_2( WinX_Err_NoRegData, "レジストリのキー「%s」のデータ「%s」が見つかりません。",
 489|        subKeyPath, name );
 490|    }
 491|    else
 492|      WinX_throw( ret );
 493|  }
 494|  if ( type != REG_SZ ) {
 495|    error2_2( WinX_Err_DifferentType, "レジストリのキー「%s」のデータ「%s」のタイプが異なります。",
 496|      subKeyPath, name );
 497|  }
 498|  ASSERT( size <= (DWORD)var_size );
 499|
 500|  ret = RegCloseKey( key );
 501|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
 502|
 503|  ERRORS_FUNC_END( WinX_getReg_s );
 504|  return  var;
 505|}
 506|
 507|
 508| 
 509|/**************************************************************************
 510|  3-7. <<< [WinX_getReg_x] レジストリの値(バイナリ)を取得する >>> 
 511|【引数】
 512|  ・HKEY   baseKey;    基準キー(HKEY_CLASSES_ROOT など、サブキーでも可)
 513|  ・char*  subKey;     キーの残りの文字列
 514|  ・char*  name;       データの名前の文字列(標準の場合は NULL)
 515|  ・char*  var;        データ(バイナリ)を格納するアドレス
 516|  ・int    var_size;   var のメモリサイズ
 517|【補足】
 518|・WinX_getReg の説明を参照。
 519|・WinX_getReg_s との違いは、取得する値の型がバイナリであることのみです。
 520|***************************************************************************/
 521|char*  WinX_getReg_x( HKEY baseKey, const char* subKeyPath,
 522|  const char* name, void* var, int var_size )
 523|{
 524|  LONG   ret;
 525|  HKEY   key;
 526|  DWORD  type;
 527|  DWORD  size = var_size;
 528|
 529|  ERRORS_FUNC_START( WinX_getReg_x );
 530|
 531|  ret = RegOpenKeyEx( baseKey, subKeyPath, 0L, KEY_READ, &key );
 532|  if ( ret != ERROR_SUCCESS ) {
 533|    if ( ret == 2 ) {
 534|      error2_1( WinX_Err_NoRegKey, "レジストリのキー「%s」が見つかりません。",
 535|        subKeyPath );
 536|    }
 537|    else {
 538|      WinX_throw( ret );
 539|    }
 540|  }
 541|
 542|  ret = RegQueryValueEx( key, name, NULL, &type, var, &size );
 543|  if ( ret == 2 )  {
 544|    error2_2( WinX_Err_NoRegData, "レジストリのキー「%s」のデータ「%s」が見つかりません。",
 545|      subKeyPath, name );
 546|  }
 547|  else if ( ret != ERROR_SUCCESS ) {
 548|    WinX_throw( ret );
 549|  }
 550|  if ( type != REG_BINARY ) {
 551|    error2_2( WinX_Err_DifferentType, "レジストリのキー「%s」のデータ「%s」のタイプが異なります。",
 552|      subKeyPath, name );
 553|  }
 554|  ASSERT( size <= (DWORD)var_size );
 555|
 556|  ret = RegCloseKey( key );
 557|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
 558|
 559|  ERRORS_FUNC_END( WinX_getReg_x );
 560|  return  var;
 561|}
 562|
 563|
 564| 
 565|/**************************************************************************
 566|  3-8. <<< [WinX_copyRegNest] レジストリをサブキーを含めてコピーする >>> 
 567|【引数】
 568|  ・HKEY   dstKey;    コピー先のキー(HKEY_CLASSES_ROOT など)
 569|  ・char*  dstPath;   コピー先のパス(dstKey からの相対)
 570|  ・HKEY   srcKey;    コピー元のキー
 571|  ・char*  dstPath;   コピー元のパス(srcKey からの相対)
 572|***************************************************************************/
 573|#ifdef  USES_EXCEPT3
 574|void  WinX_copyRegNest( HKEY dstKey, const char* dstPath,
 575|  HKEY srcKey, const char* srcPath )
 576|{
 577|  WinX_RegNest  nest;
 578|  char  dstPath2[256];
 579|  WinX_RegData  data;
 580|  bool  bKey;
 581|  char  dataX[256];
 582|
 583|  ERRORS_FUNC_START( WinX_copyRegNest );
 584|
 585|  WinX_RegData_init( &data, dataX, sizeof(dataX) );
 586|  WinX_RegNest_init( &nest, srcKey, srcPath, true );
 587|
 588|  while ( WinX_RegNest_next( &nest ) ) {
 589|
 590|    /* dstKey2, dstDataName2 を取得する */
 591|    ASSERT( dstPath2[0] != '\0' );
 592|    strcpy( dstPath2, dstPath );  strcat( dstPath2, "\\" );
 593|    strcat( dstPath2, WinX_RegNest_getStepPath( &nest ) );
 594|    StrX_cutLastOf( dstPath2, '\\' );
 595|    bKey = WinX_RegNest_getIsKey( &nest );
 596|
 597|    /* データをコピーする */
 598|    c_try {
 599|      WinX_RegNest_getData( &nest, &data );
 600|      WinX_setReg( dstKey, dstPath2, bKey, &data );
 601|    }
 602|    c_catch( Errors_Msg*, msg ) {
 603|      if ( msg->code != WinX_Err_NoRegData || !bKey )
 604|        c_throw_again();
 605|    } c_end_catch;
 606|  }
 607|
 608|  WinX_RegNest_finish( &nest );
 609|  ERRORS_FUNC_END( WinX_copyRegNest );
 610|}
 611|#endif
 612|
 613| 
 614|/**************************************************************************
 615|  3-9. <<< [WinX_delRegNest] レジストリのキーをサブキーも含めて削除する >>> 
 616|【引数】
 617|  ・HKEY   baseKey;    基準キー(HKEY_CLASSES_ROOT など、サブキーでも可)
 618|  ・char*  path;       基準キーからのパス(キーを指定してください)
 619|【補足】
 620|・キーが HKEY_CLASSES_ROOT\Display\Settings の場合、
 621|  baseKey == HKEY_CLASSES_ROOT, path == "Display\\Settings" を指定します。
 622|・すでに存在しないときでも、例外は発生しません。
 623|***************************************************************************/
 624|#ifdef  USES_EXCEPT3
 625|void  WinX_delRegNest( HKEY baseKey, const char* path )
 626|{
 627|  WinX_RegNest  nest;
 628|
 629|  ERRORS_FUNC_START( WinX_delRegNest );
 630|
 631|  WinX_RegNest_init( &nest, baseKey, path, true );
 632|
 633|  while ( WinX_RegNest_next( &nest ) ) {
 634|    WinX_delReg( baseKey, WinX_RegNest_getAbsPath( &nest ),
 635|      WinX_RegNest_getIsKey( &nest ) );
 636|  }
 637|  WinX_RegNest_finish( &nest );
 638|
 639|  WinX_delReg( baseKey, path, true );
 640|  ERRORS_FUNC_END( WinX_delRegNest );
 641|}
 642|#endif
 643| 
 644|/*------------------------------------------------------------------------*/
 645|/*  4. <<<< ◆(WinX_RegNest) サブキーを含めたレジストリの列挙 >>>> */ 
 646|/*------------------------------------------------------------------------*/
 647|
 648|void  WinX_RegNest_add( WinX_RegNest* );
 649|
 650|
 651| 
 652|/**************************************************************************
 653|  4-1. <<< [WinX_RegNest_init] 初期化する >>> 
 654|【引数】
 655|  ・char*  absPath;      列挙する基底のディレクトリ・パス
 656|  ・bool  bFinishedDir;  探索が済んだディレクトリも列挙するかどうか
 657|【補足】
 658|・初期化しても、WinX_RegNest_next するまで、ファイル名を参照することはできません。
 659|***************************************************************************/
 660|#ifdef  USES_EXCEPT3
 661|void  WinX_RegNest_init( WinX_RegNest* m, HKEY baseKey, const char* absPath,
 662|  bool bFinishedDir )
 663|{
 664|  int    i;
 665|
 666|  ERRORS_FUNC_START( WinX_RegNest_init );
 667|
 668|  m->fname = malloc( sizeof(char*) * WinX_RegNest_bufM );
 669|  m->fname_memArea = (char*)malloc( sizeof(char) * WinX_RegNest_bufM * (WinX_RegNest_nameSize + 1) );
 670|  for ( i = 0; i < WinX_RegNest_bufM; i++ )
 671|    m->fname[i] = m->fname_memArea + i * (WinX_RegNest_nameSize + 1);
 672|  m->bFinishedDir = bFinishedDir;
 673|
 674|  m->I = malloc( sizeof(int) * (WinX_nestM + 1) );
 675|
 676|  m->baseKey = baseKey;
 677|  strcpy( m->absPath, absPath );
 678|
 679|  m->nest = -1;
 680|  c_try {
 681|    WinX_RegNest_add( m );
 682|    m->bKey = ( WinX_RegNest_getDataCount( m ) == 0 );
 683|  }
 684|  c_catch ( Errors_Msg*, msg ) {
 685|    if ( msg->code != WinX_Err_CannotAddNest )  c_throw_again();
 686|    m->nest= -1;
 687|  } c_end_catch;
 688|  m->I[1] ++;
 689|
 690|  ERRORS_FUNC_END( WinX_RegNest_init );
 691|}
 692|#endif
 693|
 694| 
 695|/**************************************************************************
 696|  4-2. <<< [WinX_RegNest_finish] 後始末する >>> 
 697|***************************************************************************/
 698|void  WinX_RegNest_finish( WinX_RegNest* m )
 699|{
 700|  ERRORS_FUNC_START( WinX_RegNest_finish );
 701|  free( m->fname_memArea );
 702|  free( m->fname );
 703|  free( m->I );
 704|  ERRORS_FUNC_END( WinX_RegNest_finish );
 705|}
 706|
 707|
 708| 
 709|/**************************************************************************
 710|  4-3. <<< [WinX_RegNest_next] 次のファイルを参照する >>> 
 711|【引数】
 712|  ・返り値 : 次の候補があるか
 713|【補足】
 714|・最初、または次のファイルを参照するようにします。つまり、この関数を
 715|  呼び出すたびに、WinX_RegNest_getName 関数、WinX_RegNest_getPath 関数、
 716|  WinX_RegNest_getAbsPath 関数によって参照されるキー名と、
 717|  WinX_RegNest_getVar 関数によって参照される値が変わります。
 718|***************************************************************************/
 719|bool  WinX_RegNest_next( WinX_RegNest* m )
 720|{
 721|  bool  r;
 722|
 723|  ERRORS_FUNC_START( WinX_RegNest_next );
 724|
 725|  if ( m->nest <= 0 )  { r = false;  goto ret; }
 726|
 727|  /* 次のデータがすぐあれば返る */
 728|  m->I[m->nest] --;
 729|
 730|  if ( m->I[m->nest] >= m->I[m->nest - 1] ) {
 731|    { r = true;  goto ret; }
 732|  }
 733|
 734|  /* bFinishedDir のとき */
 735|  if ( m->bKey ) {
 736|    m->nest --;
 737|    m->bKey = false;
 738|  }
 739|
 740|  do {
 741|
 742|    /* ルートのサブキーがあるとき */
 743|    if ( m->nest == 1 ) {
 744|      if ( m->I[0] == 0 )  { r = false;  goto ret; }
 745|      m->nest --;
 746|      m->I[0] --;
 747|    }
 748|
 749|    /* ルートより下位のキーの... */
 750|    else {
 751|
 752|      /* サブキーがあるとき */
 753|      if ( WinX_RegNest_getNotExpandSubKeyCount( m ) > 0 ) {
 754|        m->nest --;
 755|        m->I[m->nest] --;
 756|      }
 757|
 758|      /* サブキーがもう無いとき */
 759|      else {
 760|
 761|        /* 処理済のキーを返すとき、そのキーを返す */
 762|        if ( m->bFinishedDir ) {
 763|          m->bKey = true;
 764|          { r = true;  goto ret; }
 765|        }
 766|
 767|        /* 次のデータかキーまで親キーへ戻る */
 768|        m->nest -= 2;
 769|        while ( m->I[m->nest] - 1 == m->I[m->nest - 1] ) {
 770|          if ( m->I[m->nest - 1] == 0 )  { r = false;  goto ret; }
 771|          m->nest --;
 772|        }
 773|        m->I[m->nest] --;
 774|      }
 775|    }
 776|
 777|    /* 次のサブキーとデータを格納する */
 778|    WinX_RegNest_add( m );
 779|    m->bKey = ( WinX_RegNest_getDataCount( m ) == 0 );
 780|
 781|  } while ( m->bKey );
 782|          /* データが無いときは、次のキーの内容を格納する */
 783|  r = true;
 784|
 785|ret:
 786|  ERRORS_FUNC_END( WinX_RegNest_next );
 787|  return  r;
 788|}
 789|
 790|
 791|
 792| 
 793|/**************************************************************************
 794|  4-4. <<< [WinX_RegNest_add] スタックに、あるキーが持つ、サブキー名とデータ名の列挙を追加する >>> 
 795|【補足】
 796|・m->I[0] 〜 m->I[m->nest] から作られるパスのキーのサブキーと
 797|  データを取得します。
 798|・サブ・キーまたはデータが無いときは追加しませんが、ネスト数(m->nest)は増えます。
 799|***************************************************************************/
 800|void  WinX_RegNest_add( WinX_RegNest* m )
 801|{
 802|  LONG  ret;
 803|  int  i, n, first;
 804|  DWORD  size;
 805|  char*  path;
 806|  FILETIME  dummyTime;
 807|  HKEY  key;
 808|
 809|  ERRORS_FUNC_START( WinX_RegNest_add );
 810|
 811|  strcpy( m->workPath, m->absPath );
 812|  if ( m->nest >= 0 ) {
 813|    strcat( m->workPath, "\\" );
 814|    for ( i = 0; i <= m->nest - 1; i++ ) {
 815|      strcat( m->workPath, m->fname[ m->I[i] ] );
 816|      strcat( m->workPath, "\\" );
 817|    }
 818|    strcat( m->workPath, m->fname[ m->I[i] ] );
 819|  }
 820|  path = m->workPath;
 821|
 822|
 823|  ret = RegOpenKeyEx( m->baseKey, path, 0L, KEY_READ, &key );
 824|  if ( ret != ERROR_SUCCESS )
 825|    error2_1( WinX_Err_CannotAddNest, "レジストリ %s がありません", path );
 826|
 827|  /* m->I[m->nest] のサブキー名の列挙を読み込む */
 828|  n = 0;
 829|  i = ( m->nest >= 0 )  ? m->I[m->nest] : -1;
 830|  first = i + 1;
 831|  for (;;) {
 832|    i++;  size = WinX_RegNest_nameSize;
 833|    ret = RegEnumKeyEx( key, n, m->fname[i], &size, NULL, NULL, NULL, &dummyTime );
 834|    if ( ret == ERROR_NO_MORE_ITEMS )
 835|      break;
 836|    n++;
 837|  }
 838|  for ( i = 0; i < n / 2; i++ ) {
 839|    char*  sw;
 840|
 841|    sw = m->fname[first + i];
 842|    m->fname[first + i] = m->fname[first + n - i - 1];
 843|    m->fname[first + n - i - 1] = sw;
 844|  }
 845|
 846|  m->I[m->nest + 1] = ( m->nest >= 0 )  ? m->I[m->nest] + n + 1:  n;
 847|  m->nest ++;
 848|
 849|
 850|  /* データ名の列挙を読み込む */
 851|  n = 0;
 852|  i = m->I[m->nest];
 853|  first = i;
 854|  for (;;) {
 855|    do {
 856|      size = WinX_RegNest_nameSize;
 857|      ret = RegEnumValue( key, n, m->fname[i], &size, NULL, NULL, NULL, NULL );
 858|      if ( ret == ERROR_NO_MORE_ITEMS )
 859|        goto  exit_for;
 860|      n++;
 861|    } while ( m->fname[i][0] == '\0' );  /*(標準)のデータは格納しない */
 862|    i++;
 863|  }
 864| exit_for:
 865|  n = i - m->I[m->nest];
 866|  for ( i = 0; i < n / 2; i++ ) {
 867|    char*  sw;
 868|
 869|    sw = m->fname[first + i];
 870|    m->fname[first + i] = m->fname[first + n - i - 1];
 871|    m->fname[first + n - i - 1] = sw;
 872|  }
 873|
 874|  m->I[m->nest + 1] = m->I[m->nest] + n - 1;
 875|  m->nest ++;
 876|
 877|  ret = RegCloseKey( key );
 878|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
 879|
 880|  ERRORS_FUNC_END( WinX_RegNest_add );
 881|}
 882|
 883|
 884|
 885| 
 886|/**************************************************************************
 887|  4-5. <<< [WinX_RegNest_getName] 現在のファイル名を参照する >>> 
 888|【補足】
 889|・フォルダの場所(絶対パス)を含まない、単独のファイル名を参照します。
 890|・folder\sub\filename.txt の filename.txt が参照されます。
 891|・m->absPath == "folder\" の場合、
 892|  WinX_RegNest_getName 関数では "filename.txt"、
 893|  WinX_RegNest_getPath 関数では "sub\filename.txt"、
 894|  WinX_RegNest_getAbsPath 関数では "folder\sub\filename.txt" が参照されます。
 895|・参照しているファイル名は、変更しないでください。
 896|***************************************************************************/
 897|char*  WinX_RegNest_getName( WinX_RegNest* m )
 898|{
 899|  return  m->fname[ m->I[m->nest] ];
 900|}
 901|
 902|
 903| 
 904|/**************************************************************************
 905|  4-6. <<< [WinX_RegNest_getStepPath] 現在の相対パスを参照する >>> 
 906|【補足】
 907|・WinX_RegNest_init 関数の absPath 引数に指定したパスからの相対パスを参照します。
 908|・参照している相対パスは、WinX_RegNest_getPath() か WinX_RegNest_getAbsPath()
 909|  のどれかが再び呼び出されると変更されます。
 910|***************************************************************************/
 911|char*  WinX_RegNest_getStepPath( WinX_RegNest* m )
 912|{
 913|  int  i;
 914|
 915|  ERRORS_FUNC_START( WinX_RegNest_getStepPath );
 916|
 917|  strcpy( m->workPath, "" );
 918|
 919|  if ( m->nest >= 0 ) {
 920|    for ( i = 0; i <= m->nest - 2; i++ ) {
 921|      strcat( m->workPath, m->fname[ m->I[i] ] );
 922|      strcat( m->workPath, "\\" );
 923|    }
 924|    if ( m->bKey )
 925|      StrX_bs( m->workPath );
 926|    else
 927|      strcat( m->workPath, m->fname[ m->I[m->nest] ] );
 928|  }
 929|
 930|  ERRORS_FUNC_END( WinX_RegNest_getStepPath );
 931|  return  m->workPath;
 932|}
 933|
 934|
 935| 
 936|/**************************************************************************
 937|  4-7. <<< [WinX_RegNest_getAbsPath] 現在の絶対パスを参照する >>> 
 938|【補足】
 939|・参照している相対パスは、WinX_RegNest_getPath() か WinX_RegNest_getAbsPath()
 940|  のどれかが再び呼び出されると変更されます。
 941|***************************************************************************/
 942|char*  WinX_RegNest_getAbsPath( WinX_RegNest* m )
 943|{
 944|  char  s[_MAX_PATH];
 945|
 946|  ERRORS_FUNC_START( WinX_RegNest_getAbsPath );
 947|
 948|  strcpy( s, WinX_RegNest_getStepPath( m ) );
 949|  strcpy( m->workPath, m->absPath );
 950|  if ( s[0] != '\0' ) {
 951|    strcat( m->workPath, "\\" );
 952|    strcat( m->workPath, s );
 953|  }
 954|
 955|  ERRORS_FUNC_END( WinX_RegNest_getAbsPath );
 956|  return  m->workPath;
 957|}
 958|
 959|
 960| 
 961|/**************************************************************************
 962|  4-8. <<< [WinX_RegNest_getData] 現在のレジストリ・データを取得する >>> 
 963|***************************************************************************/
 964|void  WinX_RegNest_getData( WinX_RegNest* m, WinX_RegData* data )
 965|{
 966|  ERRORS_FUNC_START( WinX_RegNest_getData );
 967|
 968|  WinX_getReg( m->baseKey, WinX_RegNest_getAbsPath( m ),
 969|    WinX_RegNest_getIsKey( m ), data );
 970|
 971|  ERRORS_FUNC_END( WinX_RegNest_getData );
 972|}
 973|
 974| 
 975|/**************************************************************************
 976|  4-9. <<< [WinX_RegNest_getNotExpandSubKeyCount] 現在まだ展開していないサブキーの数を返す >>> 
 977|***************************************************************************/
 978|int  WinX_RegNest_getNotExpandSubKeyCount( WinX_RegNest* m )
 979|{
 980|  return  m->I[m->nest - 1] - m->I[m->nest - 2] - 1;
 981|}
 982|
 983| 
 984|/*------------------------------------------------------------------------*/
 985|/*  5. <<<< ◆パス関係 >>>> */ 
 986|/*------------------------------------------------------------------------*/
 987| 
 988|/**************************************************************************
 989|  5-1. <<< [WinX_getWSHPath] WSH(Windws Scripting Host) のパスを返す >>> 
 990|【補足】
 991|・WSH がインストールされていなかったら NULL を返します。
 992|  5-2. <<< [WSH] Windws Scripting Host >>>
 993|・WSH(Windows Scripting Host) は Win98 以降ならデフォルトで入っています。
 994|  Win95 でも、インストールすれば使えます。
 995|***************************************************************************/
 996|#if defined(USES_FILEX) && defined(USES_EXCEPT3)
 997|char*  WinX_getWSHPath()
 998|{
 999|  static  char  path[_MAX_PATH];
1000|
1001|  StrX_cpyAbsPath( path, "WScript.exe", _MAX_PATH - 1, WinX_getWindowsPath() );
1002|  if ( FileX_isExist( path ) )  return  path;
1003|
1004|  StrX_cdFName( path, "system32" );
1005|  if ( FileX_isExist( path ) )  return  path;
1006|
1007|  return  NULL;
1008|}
1009|#endif
1010| 
1011|/**************************************************************************
1012|  5-3. <<< [WinX_getWindowsPath] Windowsフォルダのパスを返す >>> 
1013|***************************************************************************/
1014|char*  WinX_getWindowsPath()
1015|{
1016|  return  getenv( "windir" );
1017|}
1018|
1019|
1020| 
1021|/**************************************************************************
1022|  5-4. <<< [WinX_getSystemPath] Windows のシステムフォルダのパスを返す >>> 
1023|***************************************************************************/
1024|char*  WinX_getSystemPath()
1025|{
1026|  static unsigned char  var[_MAX_PATH];
1027|  unsigned long  size = sizeof(var);
1028|
1029|  GetSystemDirectory( var, size );
1030|
1031|#if 0
1032|  HKEY  key;
1033|  LONG  ret;
1034|
1035|  ret = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1036|    "Software\\Microsoft\\Windows\\CurrentVersion\\Setup",
1037|    0L, KEY_READ, &key );
1038|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1039|
1040|  ret = RegQueryValueEx( key, "SysDir", NULL, NULL, var, &size );
1041|  else if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1042|
1043|  RegCloseKey( key );
1044|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1045|#endif
1046|
1047|  return  (char*)var;
1048|}
1049|
1050|
1051| 
1052|/**************************************************************************
1053|  5-5. <<< [WinX_getDesktopPath] デスクトップのパスを参照する >>> 
1054|【補足】
1055|・通常、"c:\windows\デスクトップ" を参照します。
1056|***************************************************************************/
1057|char*  WinX_getDesktopPath()
1058|{
1059|  static unsigned char  var[_MAX_PATH];
1060|  unsigned long  size = sizeof(var);
1061|  HKEY  key;
1062|  LONG  ret;
1063|
1064|  ret = RegOpenKeyEx( HKEY_CURRENT_USER,
1065|    "Software\\Microsoft\\Windows\\CurrentVersion\\"
1066|    "Explorer\\Shell Folders", 0L, KEY_READ, &key );
1067|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1068|
1069|  ret = RegQueryValueEx( key, "Desktop", NULL, NULL, var, &size );
1070|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1071|
1072|  RegCloseKey( key );
1073|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1074|
1075|  return  (char*)var;
1076|}
1077|
1078|
1079| 
1080|/**************************************************************************
1081|  5-6. <<< [WinX_getProgramPath] Program Files のパスを参照する >>> 
1082|【補足】
1083|・通常、"c:\Program Files\" を参照します。
1084|***************************************************************************/
1085|char*  WinX_getProgramPath()
1086|{
1087|  static unsigned char  var[_MAX_PATH];
1088|  unsigned long  size = sizeof(var);
1089|  HKEY  key;
1090|  LONG  ret;
1091|
1092|  ret = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1093|    "Software\\Microsoft\\Windows\\CurrentVersion", 0L, KEY_READ, &key );
1094|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1095|
1096|  ret = RegQueryValueEx( key, "ProgramFilesDir", NULL, NULL, var, &size );
1097|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1098|
1099|  RegCloseKey( key );
1100|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1101|
1102|  return  (char*)var;
1103|}
1104|
1105|
1106| 
1107|/**************************************************************************
1108|  5-7. <<< [WinX_getSendToPath] 「送る」のパスを参照する >>> 
1109|【補足】
1110|・通常、"c:\windows\sendto" を参照します。
1111|***************************************************************************/
1112|char*  WinX_getSendToPath()
1113|{
1114|  static unsigned char  var[_MAX_PATH];
1115|  unsigned long  size = sizeof(var);
1116|  HKEY  key;
1117|  LONG  ret;
1118|
1119|  ret = RegOpenKeyEx( HKEY_CURRENT_USER,
1120|    "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
1121|    0L, KEY_READ, &key );
1122|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1123|
1124|  ret = RegQueryValueEx( key, "Shell Folders", NULL, NULL, var, &size );
1125|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1126|
1127|  RegCloseKey( key );
1128|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1129|
1130|  return  (char*)var;
1131|}
1132|
1133|
1134| 
1135|/**************************************************************************
1136|  5-8. <<< [WinX_getMyDocPath] My Documents のパスを参照する >>> 
1137|【補足】
1138|・通常、"c:\My Documents\" を参照します。
1139|***************************************************************************/
1140|char*  WinX_getMyDocPath()
1141|{
1142|  static unsigned char  var[_MAX_PATH];
1143|  unsigned long  size = sizeof(var);
1144|  HKEY  key;
1145|  LONG  ret;
1146|
1147|  ret = RegOpenKeyEx( HKEY_CURRENT_USER,
1148|    "Software\\Microsoft\\Windows\\CurrentVersion\\"
1149|    "Explorer\\Shell Folders", 0L, KEY_READ, &key );
1150|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1151|
1152|  ret = RegQueryValueEx( key, "Personal", NULL, NULL, var, &size );
1153|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1154|
1155|  RegCloseKey( key );
1156|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1157|
1158|  return  (char*)var;
1159|}
1160|
1161|
1162| 
1163|/**************************************************************************
1164|  5-9. <<< [WinX_getStartupPath] スタートアップのパスを参照する >>> 
1165|【補足】
1166|・通常、"C:\Documents and Settings\xxx\スタート メニュー\プログラム\スタートアップ" を参照します。
1167|***************************************************************************/
1168|char*  WinX_getStartupPath()
1169|{
1170|  static unsigned char  var[_MAX_PATH];
1171|  unsigned long  size = sizeof(var);
1172|  HKEY  key;
1173|  LONG  ret;
1174|
1175|  ret = RegOpenKeyEx( HKEY_CURRENT_USER,
1176|    "Software\\Microsoft\\Windows\\CurrentVersion\\"
1177|    "Explorer\\Shell Folders", 0L, KEY_READ, &key );
1178|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1179|
1180|  ret = RegQueryValueEx( key, "Startup", NULL, NULL, var, &size );
1181|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1182|
1183|  RegCloseKey( key );
1184|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1185|
1186|
1187|  return  (char*)var;
1188|}
1189|
1190|
1191| 
1192|/**************************************************************************
1193|  5-10. <<< [WinX_getTempPath] Win98 のクリーンアップに対応の TEMP パスを参照する >>> 
1194|【補足】
1195|・通常、"c:\windows\TEMP\" を参照します。
1196|・クリーンアップが TEMP に作成したフォルダを認識しないことがあります。
1197|***************************************************************************/
1198|#ifdef  USES_STRX
1199|char*  WinX_getTempPath()
1200|{
1201|  static unsigned char  var[_MAX_PATH];
1202|
1203|  strcpy( var, getenv( "TEMP" ) );
1204|  StrX_cutLastOf2( var, '\\' );
1205|
1206|  return  (char*)var;
1207|}
1208|#endif
1209|
1210| 
1211|/*------------------------------------------------------------------------*/
1212|/*  6. <<<< ◆ウィンドウ関係 >>>> */ 
1213|/*------------------------------------------------------------------------*/
1214| 
1215|/***********************************************************************
1216|  6-1. <<< [WinX_getWndRectN] ウィンドウの座標を得る(最大化などから元に戻したときの) >>> 
1217|【引数】
1218|  ・HWND  hWnd;     ウィンドウ
1219|  ・RECT*  rect;    (出力)ウィンドウの座標
1220|【補足】
1221|・最大化したときに、ほぼ画面全体の座標を得るときは、APIの GetWindowRect
1222|  を使ってください。
1223|************************************************************************/
1224|void  WinX_getWndRectN( HWND hWnd, RECT* rect )
1225|{
1226|  WINDOWPLACEMENT a;
1227|  RECT  desktopWorkArea;
1228|
1229|  GetWindowPlacement( hWnd, &a );
1230|  *rect = a.rcNormalPosition;
1231|  SystemParametersInfo( SPI_GETWORKAREA, 0, &desktopWorkArea, 0 );
1232|  rect->left += desktopWorkArea.left;
1233|  rect->right += desktopWorkArea.left;
1234|  rect->top += desktopWorkArea.top;
1235|  rect->bottom += desktopWorkArea.top;
1236|}
1237| 
1238|/***********************************************************************
1239|  6-2. <<< [WinX_setIme] 日本語 IME をオンまたはオフにする >>> 
1240|【引数】
1241|  ・HWND  hWnd;   ウィンドウ
1242|  ・bool  bOn;    日本語IMEをオンにするかどうか
1243|************************************************************************/
1244|void  WinX_setIme( HWND hWnd, bool bOn )
1245|{
1246|  HIMC  ime;
1247|
1248|  ime = ImmGetContext( hWnd );
1249|  if ( ime ) {
1250|    ImmSetOpenStatus( ime, bOn );
1251|    ImmReleaseContext( hWnd, ime );
1252|  }
1253|}
1254| 
1255|/***********************************************************************
1256|  6-3. <<< [WinX_getIme] 日本語 IME がオンかどうかを返す >>> 
1257|【引数】
1258|  ・HWND  hWnd;   ウィンドウ
1259|  ・bool  返り値;  日本語IMEをオンにするかどうか
1260|************************************************************************/
1261|bool  WinX_getIme( HWND hWnd )
1262|{
1263|  HIMC  ime;
1264|  bool  ret = false;
1265|
1266|  ime = ImmGetContext( hWnd );
1267|  if ( ime ) {
1268|    ret = ImmGetOpenStatus( ime );
1269|    ImmReleaseContext( hWnd, ime );
1270|  }
1271|
1272|  return  ret;
1273|}
1274|
1275| 
1276|/***********************************************************************
1277|  6-4. <<< [WinX_getNumOfWnd] パソコン全体のウィンドウの数を返す >>> 
1278|************************************************************************/
1279|int  WinX_getNumOfWnd()
1280|{
1281|  HWND  wnd;
1282|  int  n = 0;
1283|
1284|  for ( wnd = GetTopWindow( GetDesktopWindow() );
1285|        wnd != NULL;
1286|        wnd = GetNextWindow( wnd, GW_HWNDNEXT ) ) {
1287|    n++;
1288|  }
1289|  return  n;
1290|}
1291|
1292| 
1293|/***********************************************************************
1294|  6-5. <<< [WinX_getAllAppHWnd] 指定のプログラムのウィンドウハンドルの一覧を取得する >>> 
1295|【引数】
1296|  ・HWND*  hs;        (出力)ウィンドウハンドルの集合
1297|  ・int    hs_size;    hs のメモリサイズ
1298|  ・char*  exe_fname;  実行ファイル名
1299|  ・int  返り値;       格納した要素数
1300|************************************************************************/
1301|int  WinX_getAllAppHWnd( HWND* hs, int hs_size, const char* exe_fname )
1302|{
1303|  HWND   wnd;
1304|  HWND*  hs_first = hs;
1305|  HWND*  hs_over = (HWND*)( (char*)hs + hs_size );
1306|  char   path[_MAX_PATH];
1307|
1308|
1309|  for ( wnd = GetTopWindow( GetDesktopWindow() );
1310|        wnd != NULL;
1311|        wnd = GetNextWindow( wnd, GW_HWNDNEXT ) ) {
1312|    WinX_getExeFNameOfWnd( wnd, path );
1313|    if ( exe_fname == NULL || stricmp( path, exe_fname ) == 0 ) {
1314|      *hs = wnd;
1315|      hs++;
1316|      if ( hs >= hs_over )  break;
1317|    }
1318|  }
1319|  return  hs - hs_first;
1320|}
1321| 
1322|/*------------------------------------------------------------------------*/
1323|/*  7. <<<< ◆ディスプレイ関係 >>>> */ 
1324|/*------------------------------------------------------------------------*/
1325| 
1326|/**************************************************************************
1327|  7-1. <<< [WinX_setDisplayBppReturnValue] WinX_getDisplayBpp 関数の返り値を設定する >>> 
1328|【補足】
1329|・WinX_getDisplayBpp 関数で自動判断ができないときに使います。
1330|・0 を指定すると、自動判定に戻します。
1331|***************************************************************************/
1332|int   WinX_displayBppReturnValue = 0;
1333|
1334|void   WinX_setDisplayBppReturnValue( int bpp )
1335|{
1336|  WinX_displayBppReturnValue = bpp;
1337|}
1338|
1339| 
1340|/**************************************************************************
1341|  7-2. <<< [WinX_getDisplayBpp] ディスプレイの色のビット数を返す >>> 
1342|【補足】
1343|  ・Win2000 でも使えます。
1344|【旧バージョンの補足】
1345|・15Bpp(R5G5B5) のディスプレイの場合、16を返します。
1346|  (判断する方法はありません)
1347|・Windows 2000 では使えません。その代わり、WinX_setDisplayBppReturnValue
1348|  関数を使って本関数の返り値を設定すれば、互換性を保つことができます。
1349|***************************************************************************/
1350|int  WinX_getDisplayBpp()
1351|{
1352|  int  ret;
1353|  HDC  dc;
1354|
1355|  dc = GetDC( NULL );
1356|  ret = GetDeviceCaps( dc, BITSPIXEL );
1357|  ReleaseDC( NULL, dc );
1358|
1359|  return  ret;
1360|
1361|#if 0
1362|  static unsigned char  var[_MAX_PATH];
1363|  unsigned long  size = sizeof(var);
1364|  HKEY  key;
1365|  LONG  ret;
1366|
1367|  if ( WinX_displayBppReturnValue == 0 ) {
1368|
1369|    ret = RegOpenKeyEx( HKEY_CURRENT_USER, "Display\\Settings", 0L, KEY_READ, &key );
1370|    if ( ret != ERROR_SUCCESS ) {
1371|      ret = RegOpenKeyEx( HKEY_CURRENT_CONFIG, "Display\\Settings", 0L, KEY_READ, &key );
1372|      if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1373|    }
1374|
1375|    ret = RegQueryValueEx( key, "BitsPerPixel", NULL, NULL, var, &size );
1376|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1377|
1378|    RegCloseKey( key );
1379|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
1380|
1381|    return  atoi(var);
1382|  }
1383|  else
1384|    return  WinX_displayBppReturnValue;
1385|#endif
1386|}
1387|
1388|
1389| 
1390|/*------------------------------------------------------------------------*/
1391|/*  8. <<<< ◆プログラム実行関係 >>>> */ 
1392|/*------------------------------------------------------------------------*/
1393| 
1394|/**************************************************************************
1395|  8-1. <<< [WinX_call] プログラムを呼び出し、終了するまで待つ >>> 
1396|【引数】
1397|  ・char*  cmdline;    コマンドライン(実行ファイルパス+パラメータ)
1398|  ・int  返り値;       呼び出したプログラムの返り値
1399|***************************************************************************/
1400|#if  defined(USES_WINERR) && defined(USES_STRX)
1401|int  WinX_call( const char* cmdline )
1402|{
1403|  BOOL   r;
1404|  STARTUPINFO  st;
1405|  PROCESS_INFORMATION  pi;
1406|  DWORD  ret;
1407|  char   path[_MAX_PATH];
1408|
1409|  GetStartupInfo( &st );
1410|  StrX_getSpacedPath( cmdline, path, NULL );
1411|
1412|  r = CreateProcess( path, (char*)cmdline, NULL, NULL, FALSE,
1413|    0, NULL, NULL, &st, &pi );
1414|  if ( r == 0 ) {
1415|    ret = GetLastError();
1416|    if ( ret == 2 )
1417|      error2_1( WinX_Err_FileNotFound, "%s が見つかりません", path );
1418|    else
1419|      error();
1420|  }
1421|
1422|  WaitForSingleObject( pi.hProcess, INFINITE );
1423|
1424|  GetExitCodeProcess( pi.hProcess, &ret );
1425|
1426|  CloseHandle( pi.hProcess );
1427|
1428|  return  (int)ret;
1429|}
1430|#endif
1431| 
1432|/**************************************************************************
1433|  8-2. <<< [WinX_openHtml] HTML ページを開く >>> 
1434|【機能】
1435|・デフォルトで使用するブラウザをレジストリから調べて、
1436|  必要ならブラウザを開いて HTML ページを表示させます。
1437|【引数】
1438|  ・char*  url;           開く HTML ページの URL
1439|  ・bool bNewWnd;         新しいウィドウで開くかどうか
1440|【補足】
1441|・ローカル上、インターネット上どちらの HTML ページも開くことが出来ます。
1442|***************************************************************************/
1443|#if defined(USES_BIGSTACK) && defined(USES_STRX) && defined(USES_EXCEPT3)
1444|#if defined(USES_FILEX)
1445|void  WinX_openHtml_sub( const char* url, bool bNewWnd, int browser );
1446|
1447|void  WinX_openHtml( const char* url, bool bNewWnd )
1448|{
1449|  WinX_openHtml_sub( url, bNewWnd, 0 );
1450|}
1451|
1452|
1453|/* browser: 0=標準のブラウザ, 1=IE(for ActiveX) */
1454|void  WinX_openHtml_sub( const char* url, bool bNewWnd, int browser )
1455|{
1456|  enum { size = 512 };
1457|  char*  subName;
1458|  char   url2[size];
1459|  char  command[size];
1460|  char  data[size];
1461|  char  service[size];
1462|  char  topic[size];
1463|
1464|  ERRORS_FUNC_START( WinX_openHtml );
1465|
1466|  /* # 付きのパスなら、サブ・ネーム付きの URL とみなす */
1467|  subName = StrX_refURLSubName( url );
1468|  strcpy( url2, url );
1469|  if ( *subName == '\0' ) {
1470|    strcpy( url2, url );
1471|  }
1472|  else {
1473|    FILE*  f;
1474|    char   regularURL[_MAX_PATH];
1475|
1476|    if ( StrX_isUrl( url ) )
1477|      strcpy( regularURL, url );
1478|    else
1479|      StrX_chgPathToUrl( regularURL, url );
1480|
1481|    FileX_getTmpPath3( NULL, "url", "htm", url2 );
1482|    f = fopen( url2, "wt" );
1483|    fputs( "<HTML>\n", f );
1484|    fputs( "<HEAD>\n", f );
1485|    fputs( "  <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;CHARSET=x-sjis\">\n", f );
1486|    fputs( "  <TITLE>移動中</TITLE>\n", f );
1487|    fputs( "</HEAD>\n", f );
1488|    fputs( "\n", f );
1489|    fputs( "<BODY onLoad=\"setTimeout('nextp()',1000)\" BGCOLOR=\"#ffffff\">\n", f );
1490|    fputs( "\n", f );
1491|    fputs( "<SCRIPT LANGUAGE=\"JavaScript\">\n", f );
1492|    fputs( "<!--\n", f );
1493|    fprintf( f, "function nextp(){location.href=\"%s\"}\n", regularURL );
1494|    fputs( "//-->\n", f );
1495|    fputs( "</SCRIPT>\n", f );
1496|    fputs( "\n", f );
1497|    fputs( "<P><CENTER></CENTER>\n", f );
1498|    fputs( "<CENTER>\n", f );
1499|    fputs( "\n", f );
1500|    fprintf( f, "<P><A href=\"%s\">ジャンプしています</A><P>\n", regularURL );
1501|    fputs( "\n", f );
1502|    fputs( "</CENTER>\n", f );
1503|    fputs( "</BODY>\n", f );
1504|    fputs( "</HTML>\n", f );
1505|    fclose( f );
1506|  }
1507|
1508|  /* 標準のブラウザの情報を取得する */
1509|  if ( browser == 0 ) {
1510|    c_try {
1511|      WinX_getReg_s( HKEY_CLASSES_ROOT, "http\\shell\\open\\command",
1512|        NULL, command, size );
1513|      WinX_getReg_s( HKEY_CLASSES_ROOT, "http\\shell\\open\\ddeexec",
1514|        NULL, data, size );
1515|      WinX_getReg_s( HKEY_CLASSES_ROOT, "http\\shell\\open\\ddeexec\\Application",
1516|        NULL, service, size );
1517|      WinX_getReg_s( HKEY_CLASSES_ROOT, "http\\shell\\open\\ddeexec\\Topic",
1518|        NULL, topic, size );
1519|    }
1520|    c_catch ( Errors_Msg*, msg ) {
1521|      if ( msg->code == WinX_Err_NoRegKey )  bNewWnd = true;
1522|      else  c_throw_again();
1523|    } c_end_catch;
1524|  }
1525|  else if ( browser == 1 ) {
1526|    strcpy( command, WinX_getWindowsPath() );
1527|    StrX_addFName( command, "explorer.exe \"%1\"" );
1528|  }
1529|
1530|
1531|  /* 開く */
1532|  if ( bNewWnd ) {
1533|    if ( strstr( command, "%1" ) != NULL )
1534|      StrX_rep( command, size, "%1", url2 );
1535|    else
1536|      { strcat( command, " \"" );  strcat( command, url2 );  strcat( command, "\"" ); }
1537|    WinExec( command, SW_SHOWNORMAL );
1538|  }
1539|  else {
1540|    StrX_rep( data, size, "%1", url2 );
1541|    WinX_sendDDE( command, service, topic, data, strlen( data ), WinX_Request );
1542|  }
1543|
1544|  ERRORS_FUNC_END( WinX_openHtml );
1545|}
1546|#endif
1547|#endif
1548|
1549| 
1550|/**************************************************************************
1551|  8-3. <<< [WinX_openIE] Internet Explorer を開く(AcriveX用) >>> 
1552|***************************************************************************/
1553|void  WinX_openIE( const char* url )
1554|{
1555|  WinX_openHtml_sub( url, true, 1 );
1556|}
1557|
1558| 
1559|/**************************************************************************
1560|  8-4. <<< [WinX_openByNotePad] メモ帳でファイルを開く >>> 
1561|【引数】
1562|  ・char*  path;          開くファイルのパス
1563|***************************************************************************/
1564|void  WinX_openByNotepad( const char* path )
1565|{
1566|  char  cmd[_MAX_PATH*2];
1567|
1568|  sprintf( cmd, "%s\\notepad.exe \"%s\"", WinX_getWindowsPath(), path );
1569|
1570|  WinExec( cmd, SW_SHOWNORMAL );
1571|}
1572|
1573| 
1574|/**************************************************************************
1575|  8-5. <<< [WinX_openFile] ユーザ的にファイルを開く(ダブルクリック的) >>> 
1576|【引数】
1577|  ・char*  path;        ファイルパス
1578|【補足】
1579|・ファイルをダブルクリックしてファイルを開くことと同じことをします。
1580|【内部補足】
1581|・次の DDE コマンドには対応していません。(DDE を使わないで開きます)
1582|  [FindFolder("%l", %I)]
1583|  [ViewFolder("%l","%l",%S)]
1584|  [ViewFolder(%l, %I, %S)]
1585|  [ExploreFolder(%l, %I, %S)]
1586|  [printto("%1","%2","%3","%4")]
1587|  [ShellFile("%1","%1",%S)]
1588|・shellEx キーの内容には対応していません。
1589|  (GUID は、HKEY_CLASSES_ROOT\CLSID にありますが)
1590|・WinX_Err_NoRegKey 例外が出ることがあります。
1591|***************************************************************************/
1592|#ifdef  USES_STRX
1593|#if defined(USES_BIGSTACK) && defined(USES_FILEX) && defined(USES_EXCEPT3)
1594|void  WinX_openFile( const char* path )
1595|{
1596|  HKEY  shellKey;
1597|  char  keyPath[256];
1598|  char  action[256];
1599|  DWORD type;
1600|  DWORD size;
1601|  DWORD index;
1602|  LONG  ret;
1603|
1604|  ERRORS_FUNC_START( WinX_openFile );
1605|
1606|  ASSERT( ! FileX_isDir( path ) );
1607|  ASSERT( FileX_isExist( path ) );
1608|
1609|#if 0
1610|  char* p1;
1611|  bool  bDDE;
1612|  char  command[256];
1613|#endif
1614|
1615|  /* # 付きのパスなら、サブ・ネーム付きの URL とみなす */
1616|  {
1617|    char*  subName = StrX_refURLSubName( path );
1618|    if ( *subName != '\0' ) {
1619|      WinX_openHtml( path, true );
1620|      return;
1621|    }
1622|  }
1623|
1624|  /* HKEY_CLASSES_ROOT\.(ext)\(標準) のキーの値を keyPath に取得する */
1625|  c_try {
1626|    WinX_getReg_s( HKEY_CLASSES_ROOT, StrX_refExt( path ) - 1, NULL, keyPath, sizeof(keyPath) );
1627|
1628|  }
1629|  c_catch ( Errors_Msg*, msg ) {
1630|    if ( msg->code == WinX_Err_NoRegKey )  strcpy( keyPath, "*" );
1631|    else  c_throw_again();
1632|  } c_end_catch;
1633|
1634|  /* HKEY_CLASSES_ROOT\(typeName)\shell キーを shellKey とする */
1635|  /* HKEY_CLASSES_ROOT\(typeName)\shell\(標準) のキーの値を action に取得する */
1636|  strcat( keyPath, "\\shell" );
1637|  ret = RegOpenKeyEx( HKEY_CLASSES_ROOT, keyPath, 0L, KEY_READ, &shellKey );
1638|  if ( ret != ERROR_SUCCESS )  WinX_error2( ret );
1639|  size = sizeof(action);
1640|  ret = RegQueryValueEx( shellKey, NULL, NULL, &type, action, &size );
1641|
1642|  /* 上記キー(デフォルト・アクション)が無かったら */
1643|  if ( ret != ERROR_SUCCESS || action[0] == '\0' ) {
1644|
1645|    /* HKEY_CLASSES_ROOT\(typeName)\shell\open キーがあれば action に open を代入する */
1646|    index = 0;
1647|    do {
1648|      ret = RegEnumKey( shellKey, index, action, sizeof(action) );
1649|      index++;
1650|    } while ( strcmp( action, "open" ) != 0 && ret == ERROR_SUCCESS );
1651|
1652|    RegCloseKey( shellKey );
1653|
1654|    /* 上記キーが無ければ */
1655|    if ( ret != ERROR_SUCCESS ) {
1656|
1657|      /* HKEY_CLASSES_ROOT\*\shell キーを shellKey とする */
1658|      /* HKEY_CLASSES_ROOT\*\shell\\(標準)キーに値があれば action に代入する */
1659|      strcpy( keyPath, "*\\shell" );
1660|      RegOpenKeyEx( HKEY_CLASSES_ROOT, keyPath, 0L, KEY_READ, &shellKey );
1661|      size = sizeof(action);
1662|      if ( RegQueryValueEx( shellKey, NULL, NULL, &type, action, &size )
1663|            != ERROR_SUCCESS ||  *action == '\0' ) {
1664|
1665|        /* 無ければ HKEY_CLASSES_ROOT\*\shell のサブキー名を action 代入する */
1666|        RegEnumKey( shellKey, 0, action, sizeof(action) );
1667|      }
1668|      RegCloseKey( shellKey );
1669|    }
1670|  }
1671|  else
1672|    RegCloseKey( shellKey );
1673|
1674|#if 1
1675|  ShellExecute( NULL, action, path, "", ".", SW_SHOWNORMAL );
1676|
1677|#else  /* 以下は、Word ファイルの DDE がうまくいかないため却下 */
1678|
1679|  /* 各種実行パラメータを取得する */
1680|  p1 = strchr( keyPath, '\0' );
1681|  bDDE = true;
1682|
1683|  sprintf( p1, "\\%s\\command", action );
1684|  WinX_getReg_s( HKEY_CLASSES_ROOT, keyPath, NULL, command, sizeof(command) );
1685|  sprintf( p1, "\\%s", action );
1686|
1687|  /* 実行する */
1688|  WinX_openFile_sub( keyPath, command, path, action );
1689|#endif
1690|
1691|  ERRORS_FUNC_END( WinX_openFile );
1692|}
1693|#endif
1694|#endif
1695|
1696|
1697| 
1698|/**************************************************************************
1699|  8-6. <<< [WinX_openFile2] ユーザ的にファイルを開く(右クリック的) >>> 
1700|【引数】
1701|  ・char*  path;    ファイルパス
1702|  ・char*  action;  アクション名("" または NULL で、デフォルトアクション)
1703|  ・bool   bAll;    対応する拡張子が無いときに全拡張子の情報を使って開くか
1704|【補足】
1705|・ファイルをダブルクリックしたり右クリックしてファイルを開くことと
1706|  同じことをします。
1707|***************************************************************************/
1708|#if defined(USES_BIGSTACK) && defined(USES_FILEX) && defined(USES_EXCEPT3)
1709|void  WinX_openFile2( const char* path, const char* action )
1710|{
1711|#if 1
1712|  ShellExecute( NULL, action, path, "", ".", SW_SHOWNORMAL );
1713|  return;
1714|#else  /* 以下は、Word ファイルの DDE がうまくいかないため却下 */
1715|  char  keyPath[256];
1716|  char  command[256];
1717|  char  typeName[256];
1718|
1719|  ERRORS_FUNC_START( WinX_openFile2 );
1720|
1721|  /* デフォルトアクションを実行する */
1722|  if ( action == NULL || action[0] == '\0' ) {
1723|    WinX_openFile( path );
1724|    ERRORS_FUNC_END( WinX_openFile2 );
1725|    return;
1726|  }
1727|
1728|  c_try {
1729|    /* HKEY_CLASSES_ROOT\.(ext)\(標準) のキーの値を keyPath に取得する */
1730|    WinX_getReg_s( HKEY_CLASSES_ROOT, StrX_refExt( path ) - 1, NULL, typeName, sizeof(typeName) );
1731|
1732|    /* HKEY_CLASSES_ROOT\(typeName)\shell\(action) キーの名前を keyPath に取得する */
1733|    /* HKEY_CLASSES_ROOT\(typeName)\shell\(action)\command キーの値を command に取得する */
1734|    sprintf( keyPath, "%s\\shell\\%s\\command", typeName, action );
1735|    WinX_getReg_s( HKEY_CLASSES_ROOT, keyPath, NULL, command, sizeof(command) );
1736|    sprintf( keyPath, "%s\\shell\\%s", typeName, action );
1737|  }
1738|  c_catch ( Errors_Msg*, msg ) {
1739|    if ( msg->code == WinX_Err_NoRegKey )
1740|      command[0] = '\0';
1741|    else
1742|      c_throw_again();
1743|  } c_end_catch;
1744|
1745|  /* command に取得できなかったら */
1746|  if ( command[0] == '\0' && bAll ) {
1747|
1748|    /* HKEY_CLASSES_ROOT\*\shell\(action) キーの名前を keyPath に取得する */
1749|    /* HKEY_CLASSES_ROOT\*\shell\(action)\command キーの値を command に取得する */
1750|    c_try {
1751|      sprintf( keyPath, "*\\shell\\%s\\command", action );
1752|      WinX_getReg_s( HKEY_CLASSES_ROOT, keyPath, NULL, command, sizeof(command) );
1753|      sprintf( keyPath, "*\\shell\\%s", action );
1754|    }
1755|    c_catch ( Errors_Msg*, msg ) {
1756|      if ( msg->code == WinX_Err_NoRegKey )
1757|        command[0] = '\0';
1758|      else
1759|        c_throw_again();
1760|    } c_end_catch;
1761|  }
1762|
1763|  /* command に取得できなかったらエラー */
1764|  if ( command[0] == '\0' ) {
1765|    error2_2( WinX_Err_NotMatchActionName,
1766|      "ファイル %s のアクション %s がありません。", path, action );
1767|  }
1768|
1769|  /* 実行する */
1770|  WinX_openFile_sub( keyPath, command, path, action );
1771|  ERRORS_FUNC_END( WinX_openFile2 );
1772|#endif
1773|}
1774|#endif
1775| 
1776|/**************************************************************************
1777|  8-7. <<< [WinX_openFile_sub] WinX_openFile のサブルーチン >>> 
1778|【引数】
1779|  ・char*  actionPath; アクションキーのパス(内部で書きかえられます、サイズは256以上)
1780|  ・char*  command;    レジストリにあるコマンドデータ(内部で書きかえられます、サイズは256以上)
1781|  ・char*  path;       ファイルパス
1782|  ・char*  action;     アクション名
1783|***************************************************************************/
1784|#if defined(USES_BIGSTACK) && defined(USES_FILEX) && defined(USES_EXCEPT3)
1785|void  WinX_openFile_sub( char* actionPath, char* command, const char* path,
1786|  const char* action )
1787|{
1788|  char*  p1 = strchr( actionPath, '\0' );
1789|  bool  bDDE;
1790|  char  ifexec[256];
1791|  char  data[256];
1792|  char  service[256];
1793|  char  topic[256];
1794|  char  shortPath[_MAX_PATH];
1795|  char  longPath[_MAX_PATH];
1796|
1797|  ERRORS_FUNC_START( WinX_openFile_sub );
1798|
1799|  bDDE = true;
1800|
1801|  GetShortPathName( path, shortPath, sizeof(shortPath) );
1802|  StrX_toLongPath( longPath, shortPath );
1803|  if ( strstr( command, "%1" ) == NULL )
1804|    ;//{ strcat( command, " " );  strcat( command, shortPath ); }
1805|  else
1806|    StrX_rep( command, 256, "%1", shortPath );
1807|
1808|  c_try {
1809|    strcpy( p1, "\\ddeexec" );
1810|    WinX_getReg_s( HKEY_CLASSES_ROOT, actionPath, NULL, data, sizeof(data) );
1811|    StrX_rep( data, sizeof(data), "%1", longPath );
1812|    if ( strstr( data, "%l" ) != NULL )
1813|      bDDE = false;
1814|  }
1815|  c_catch ( Errors_Msg*, msg ) {
1816|    bDDE = false;
1817|  } c_end_catch;
1818|
1819|  /* DDE を実行する */
1820|  if ( bDDE ) {
1821|    strcpy( p1, "\\ddeexec\\application" );
1822|    WinX_getReg_s( HKEY_CLASSES_ROOT, actionPath, NULL, service, sizeof(service) );
1823|    c_try {
1824|      strcpy( p1, "\\ddeexec\\ifexec" );
1825|      WinX_getReg_s( HKEY_CLASSES_ROOT, actionPath, NULL, ifexec, sizeof(ifexec) );
1826|    }
1827|    c_catch ( Errors_Msg*, msg ) {
1828|      ifexec[0] = '\0';
1829|    } c_end_catch;
1830|    strcpy( p1, "\\ddeexec\\topic" );
1831|    WinX_getReg_s( HKEY_CLASSES_ROOT, actionPath, NULL, topic, sizeof(topic) );
1832|
1833|    if ( ifexec[0] == '\0' ) {
1834|      #if ERRORS_DEBUG_FALSE
1835|        WS( command );
1836|        WS( data );
1837|      #endif
1838|      WinX_sendDDE( command, service, topic, data, strlen( data ), WinX_Execute );
1839|    }
1840|    else
1841|      WinX_sendDDE( ifexec, service, topic, data, strlen( data ), WinX_Execute );
1842|  }
1843|
1844|  /* コマンドを実行する */
1845|  else {
1846|    WinExec( command, SW_SHOWNORMAL );
1847|  }
1848|  ERRORS_FUNC_END( WinX_openFile_sub );
1849|}
1850|#endif
1851| 
1852|/**************************************************************************
1853|  8-8. <<< [WinX_openFolder] フォルダを開く >>> 
1854|【引数】
1855|  ・char*  path;        フォルダパス
1856|***************************************************************************/
1857|void  WinX_openFolder( const char* path )
1858|{
1859|  char  path2[_MAX_PATH*2];
1860|
1861|  ERRORS_FUNC_START( WinX_openFolder );
1862|
1863|  sprintf( path2, "%s\\explorer.exe \"%s\"", WinX_getWindowsPath(), path );
1864|  WinExec( path2, SW_SHOWNORMAL );
1865|
1866|  ERRORS_FUNC_END( WinX_openFolder );
1867|}
1868| 
1869|/**************************************************************************
1870|  8-9. <<< [WinX_openFolder2] フォルダを開く >>> 
1871|【引数】
1872|  ・char*  path;      開くフォルダのパス
1873|  ・bool  bTree;      フォルダツリーを表示するかどうか
1874|  ・bool  bRoot;      path をツリーのルートとするかどうか(bTree==true のとき有効)
1875|  ・char*  selPath;   選択状態にするファイルパス(path からの相対)(NULL=選択しない)
1876|***************************************************************************/
1877|void  WinX_openFolder2( const char* path, bool bTree, bool bRoot, const char* selPath )
1878|{
1879|  char  path2[_MAX_PATH*2];
1880|
1881|  ERRORS_FUNC_START( WinX_openFolder2 );
1882|
1883|  ASSERT( selPath == NULL );  /* 未対応 */
1884|
1885|  if ( bTree && bRoot ) {
1886|    sprintf( path2, "%s\\explorer.exe /e,/root,\"%s\"", WinX_getWindowsPath(), path );
1887|    WinExec( path2, SW_SHOWNORMAL );
1888|  }
1889|  else {
1890|    ( bTree ? WinX_openExplorer( path ) : WinX_openFolder( path ) );
1891|  }
1892|
1893|  ERRORS_FUNC_END( WinX_openFolder2 );
1894|}
1895|
1896|
1897| 
1898|/**************************************************************************
1899|  8-10. <<< [WinX_openExplorer] エクスプローラを開く >>> 
1900|【引数】
1901|  ・char*  path;        フォルダパス
1902|***************************************************************************/
1903|void  WinX_openExplorer( const char* path )
1904|{
1905|  char  path2[_MAX_PATH*2];
1906|
1907|  ERRORS_FUNC_START( WinX_openExplorer );
1908|
1909|  sprintf( path2, "%s\\explorer.exe /e,\"%s\"", WinX_getWindowsPath(), path );
1910|  WinExec( path2, SW_SHOWNORMAL );
1911|
1912|  ERRORS_FUNC_END( WinX_openExplorer );
1913|}
1914| 
1915|/**************************************************************************
1916|  8-11. <<< [WinX_getExeFNameOfWnd] 指定ウィンドウの実行ファイルのパスを取得する >>> 
1917|【引数】
1918|  ・HWND  hWnd;       調べるウィンドウハンドル
1919|  ・char*  exe_fname; (出力)実行ファイルのファイル名(メモリサイズは、_MAX_PATH)
1920|  ・bool  返り値;     成功したかどうか
1921|【補足】
1922|・exe_fname は、パスではなくファイル名です。
1923|・Windows NT4.0以前では使えません。
1924|・参考 http://techtips.belution.com/ja/vc/0022/
1925|***************************************************************************/
1926|#include <tlhelp32.h>
1927|
1928|bool  WinX_getExeFNameOfWnd( HWND wnd, char* exe_fname )
1929|{
1930|  bool    ret = false;
1931|  DWORD   wnd_procId;
1932|  HANDLE  snapshot;
1933|  PROCESSENTRY32  proc;
1934|
1935|  /* ToolHelp 関数ポインタ */
1936|  HANDLE (WINAPI *CreateSnapshot)( DWORD, DWORD );
1937|  BOOL (WINAPI *Process32First)( HANDLE, LPPROCESSENTRY32 );
1938|  BOOL (WINAPI *Process32Next)( HANDLE, LPPROCESSENTRY32 );
1939|
1940|  /* ウィンドウのプロセスIDを取得する */
1941|  GetWindowThreadProcessId( wnd , &wnd_procId );
1942|
1943|  /* DLL 関数のアドレスを取得する */
1944|  CreateSnapshot = (HANDLE(WINAPI*)(DWORD,DWORD)) GetProcAddress(
1945|     GetModuleHandle("kernel32.dll"), "CreateToolhelp32Snapshot" );
1946|  Process32First= (BOOL(WINAPI*)(HANDLE,LPPROCESSENTRY32)) GetProcAddress(
1947|     GetModuleHandle("kernel32.dll"), "Process32First" );
1948|  Process32Next= (BOOL(WINAPI*)(HANDLE,LPPROCESSENTRY32))GetProcAddress(
1949|     GetModuleHandle("kernel32.dll"), "Process32Next" );
1950|
1951|  if ( !CreateSnapshot || !Process32First || !Process32Next )
1952|    return FALSE;
1953|
1954|
1955|  /* 全プロセスから、一致するウィンドウを検索する */
1956|  snapshot = CreateSnapshot( TH32CS_SNAPPROCESS , 0 );  /* open */
1957|  if ( snapshot == (HANDLE)-1 )  error();
1958|
1959|  proc.dwSize = sizeof(PROCESSENTRY32);
1960|  if ( Process32First( snapshot, &proc ) ) {
1961|    do {
1962|      if ( proc.th32ProcessID == wnd_procId ) {
1963|        strcpy( exe_fname, proc.szExeFile );
1964|        ret = true;
1965|        break;
1966|      }
1967|    } while ( Process32Next( snapshot, &proc ) );
1968|  }
1969|  CloseHandle( snapshot );
1970|
1971|  return  ret;
1972|}
1973|
1974|/**************************************************************************
1975|  8-12. <<< [WinX_sendMsgToExe] 指定の実行ファイルの全てのウィンドウにメッセージを送る >>>
1976|【引数】
1977|  ・char*  exe_path;   実行ファイルパス(フォルダパスは無視されます)
1978|***************************************************************************/
1979|void  WinX_sendPostMsgToExe( int op, const char* exe_path, UINT message, WPARAM wParam, LPARAM lParam );
1980|
1981|void  WinX_sendMsgToExe( const char* exe_path, UINT message, WPARAM wParam, LPARAM lParam )
1982|{
1983|  WinX_sendPostMsgToExe( 0, exe_path, message, wParam, lParam );
1984|}
1985|
1986|/**************************************************************************
1987|  8-13. <<< [WinX_postMsgToExe] 指定の実行ファイルの全てのウィンドウにメッセージを投げる >>>
1988|【引数】
1989|  ・char*  exe_path;   実行ファイルパス(フォルダパスは無視されます)
1990|***************************************************************************/
1991|void  WinX_postMsgToExe( const char* exe_path, UINT message, WPARAM wParam, LPARAM lParam )
1992|{
1993|  WinX_sendPostMsgToExe( 1, exe_path, message, wParam, lParam );
1994|}
1995|
1996|/**************************************************************************
1997|  8-14. <<< [WinX_sendPostMsgToExe] WinX_sendMsgToExe, WinX_postMsgToExe のサブルーチン >>>
1998|***************************************************************************/
1999|void  WinX_sendPostMsgToExe( int op, const char* exe_path, UINT message, WPARAM wParam, LPARAM lParam )
2000|{
2001|  HWND   wnd;
2002|  HWND*  wnds;
2003|  int    nWnd;
2004|  int    iWnd;
2005|  char  path[_MAX_PATH];
2006|  char*  exe_fname = StrX_refFName( exe_path );
2007|
2008|  /* ウィンドウの数 nWnd を得る */
2009|  nWnd = 0;
2010|  for ( wnd = GetTopWindow( GetDesktopWindow() );
2011|        wnd != NULL;
2012|        wnd = GetNextWindow( wnd, GW_HWNDNEXT ) ) {
2013|    nWnd ++;
2014|  }
2015|
2016|  wnds = malloc( sizeof(HWND) * nWnd );
2017|
2018|  /* 全ウィンドウのハンドルを集める(集めておくのはクローズへの対応) */
2019|  iWnd = 0;
2020|  for ( wnd = GetTopWindow( GetDesktopWindow() );
2021|        wnd != NULL;
2022|        wnd = GetNextWindow( wnd, GW_HWNDNEXT ) ) {
2023|    wnds[iWnd] = wnd;
2024|    iWnd++;
2025|  }
2026|
2027|
2028|  /* 対象となるウィンドウ全てにメッセージを送る */
2029|  for ( iWnd = 0; iWnd < nWnd; iWnd++ ) {
2030|    WinX_getExeFNameOfWnd( wnds[iWnd], path );
2031|    if ( stricmp( path, exe_fname ) == 0 ) {
2032|      if ( op == 0 )  SendMessage( wnds[iWnd], message, wParam, lParam );
2033|      if ( op == 1 )  PostMessage( wnds[iWnd], message, wParam, lParam );
2034|    }
2035|  }
2036|
2037|  free( wnds );
2038|}
2039| 
2040|/**************************************************************************
2041|  8-15. <<< [WinX_isRunning] 実行ファイルが実行中(開いている)かどうかを返す >>> 
2042|【引数】
2043|  ・char*  exe_path;   実行ファイルパス(フォルダパスは無視されます)
2044|***************************************************************************/
2045|bool  WinX_isRunning( const char* exe_path )
2046|{
2047|#if 1
2048|  bool    ret = false;
2049|  HANDLE  snapshot;
2050|  PROCESSENTRY32  proc;
2051|  char*  exe_fname = StrX_refFName( exe_path );
2052|
2053|  /* ToolHelp 関数ポインタ */
2054|  HANDLE (WINAPI *CreateSnapshot)( DWORD, DWORD );
2055|  BOOL (WINAPI *Process32First)( HANDLE, LPPROCESSENTRY32 );
2056|  BOOL (WINAPI *Process32Next)( HANDLE, LPPROCESSENTRY32 );
2057|
2058|  /* DLL 関数のアドレスを取得する */
2059|  CreateSnapshot = (HANDLE(WINAPI*)(DWORD,DWORD)) GetProcAddress(
2060|     GetModuleHandle("kernel32.dll"), "CreateToolhelp32Snapshot" );
2061|  Process32First= (BOOL(WINAPI*)(HANDLE,LPPROCESSENTRY32)) GetProcAddress(
2062|     GetModuleHandle("kernel32.dll"), "Process32First" );
2063|  Process32Next= (BOOL(WINAPI*)(HANDLE,LPPROCESSENTRY32))GetProcAddress(
2064|     GetModuleHandle("kernel32.dll"), "Process32Next" );
2065|
2066|  if ( !CreateSnapshot || !Process32First || !Process32Next )
2067|    error();
2068|
2069|  snapshot = CreateSnapshot( TH32CS_SNAPPROCESS , 0 );  /* open */
2070|  if ( snapshot == (HANDLE)-1 )  error();
2071|
2072|  proc.dwSize = sizeof(PROCESSENTRY32);
2073|  if ( Process32First( snapshot, &proc ) ) {
2074|    do {
2075|      if ( stricmp( exe_fname, proc.szExeFile ) == 0 ) {
2076|        ret = true;
2077|        break;
2078|      }
2079|    } while ( Process32Next( snapshot, &proc ) );
2080|  }
2081|  CloseHandle( snapshot );
2082|
2083|  return  ret;
2084|#else
2085|  HWND  targetWnd;
2086|  char  path[_MAX_PATH];
2087|  char*  exe_fname = StrX_refFName( exe_path );
2088|
2089|  for ( targetWnd = GetTopWindow( GetDesktopWindow() );
2090|        targetWnd != NULL;
2091|        targetWnd = GetNextWindow( targetWnd, GW_HWNDNEXT ) ) {
2092|
2093|    WinX_getExeFNameOfWnd( targetWnd, path );
2094|    if ( stricmp( path, exe_fname ) == 0 ) {
2095|      return  true;
2096|    }
2097|  }
2098|  return  false;
2099|#endif
2100|}
2101| 
2102|/*------------------------------------------------------------------------*/
2103|/*  9. <<<< ◆エクスプローラメニュー関係 >>>> */ 
2104|/*------------------------------------------------------------------------*/
2105|
2106|void  WinX_openFile_sub( char* shellPath, char* command, const char* path,
2107|  const char* action );
2108|int  WinX_getFTypeInfos_sub( HKEY shellKey, int iSubKey, WinX_FType* type );
2109|
2110| 
2111|/**************************************************************************
2112|  9-1. <<< [WinX_setExtApp] 拡張子をアプリケーションに関連付けする >>> 
2113|【引数】
2114|  ・char*  ext;         拡張子(3バイトまで)
2115|  ・char*  explain;     ファイルタイプの説明
2116|  ・char*  actionName;  アクション名(英語)
2117|  ・char*  actionTitle; アクション・表題(右クリック・メニューの項目)
2118|  ・char*  command;     アクション・コマンド、実行するアプリケーション
2119|  ・char*  iconPath;    アイコン・ファイル・パス
2120|  ・int    iconNum;     iconPath 中のアイコン番号
2121|  ・bool   bDownChk;    ダウンロード時に確認するかどうか
2122|【補足】
2123|・actionTitle に、アクセスキー(例:(&A))を指定できます。
2124|・actionName を "open" にしないと、WinX_setNewFile 関数によって、
2125|  新規作成を登録できなくなります。
2126|・command には、実行ファイルをフルパスで指定してください。
2127|・iconPath にアイコン・リソースを含む実行ファイルを指定した場合、
2128|  iconNum に0以上の値を指定してください。
2129|・再起動するかフォルダオプションでアイコンを選択しない限り、
2130|  アイコンの表示は変化しません。
2131|・すでに関連付けしてある場合、それまで関連付けしてあったアクションは、
2132|  残ります(右クリック・メニューによる)。
2133|【内部補足】
2134|・デフォルトではレジストリに、.拡張子と、拡張子+"file" という名前の
2135|  サブ・キーが作られます。
2136|  例:「.ext」キーと、「extfile」キー
2137|***************************************************************************/
2138|#ifdef  USES_BIGSTACK
2139|void  WinX_setExtApp( const char* ext, const char* explain,
2140|  const char* actionName, const char* actionTitle, const char* command,
2141|  const char* iconPath, int iconNum, bool bDefault, bool bDownChk )
2142|{
2143|  enum { type_max = 2048 };
2144|  HKEY  key;
2145|  LONG  ret;
2146|  static  char  flags11[4] = { 0x00, 0x00, 0x00, 0x00 }; /* ダウンロード時に確認する */
2147|  static  char  flags10[4] = { 0x00, 0x00, 0x01, 0x00 }; /* ダウンロード時に確認しない */
2148|  static  char  flags2[4] = { 0x01, 0x00, 0x00, 0x00 };
2149|  char*  type;
2150|  int    type_len;
2151|  char*  s;
2152|  DWORD  dwDisp;
2153|
2154|  ERRORS_FUNC_START( WinX_setExtApp );
2155|
2156|  #ifdef  WINX_ENABLE_DEBUG_MODE
2157|    Errors_printf( "WinX_setExtApp():" );
2158|    Errors_printf( "  ext = %s, explain = %s", ext, explain );
2159|    Errors_printf( "  actionName = %s, actionTitle = %s, command = %s",
2160|      actionName, actionTitle, command );
2161|    Errors_printf( "  iconPath = %s, iconNum = %d, bDefault = %d, bDownChk = %d",
2162|      iconPath, iconNum, bDefault, bDownChk );
2163|  #endif
2164|
2165|  BigStack_start();
2166|  type = BigStack_alloc( type_max );
2167|  s = BigStack_alloc( type_max );
2168|
2169|  strcpy( s, "." );  strcat( s, ext );
2170|  ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
2171|    REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2172|  #ifdef  WINX_ENABLE_DEBUG_MODE
2173|    MARK();  WS( s );  WD( ret );
2174|  #endif
2175|  if ( ret == ERROR_SUCCESS ) {
2176|    type_len = type_max;
2177|    ret = RegQueryValueEx( key, NULL, NULL, NULL, type, &type_len );
2178|    #ifdef  WINX_ENABLE_DEBUG_MODE
2179|      MARK();  WS( type );  WD( ret );
2180|    #endif
2181|    if ( ret == 2 || type[0] == '\0' ) {
2182|      strcpy( type, ext );  strcat( type, "file" );
2183|      type_len = strlen( type );
2184|      ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)type, type_len );
2185|      #ifdef  WINX_ENABLE_DEBUG_MODE
2186|        MARK();  WS( type );  WD( ret );
2187|      #endif
2188|    }
2189|    if ( RegCloseKey( key ) != ERROR_SUCCESS )  WinX_throw( ret );
2190|  }
2191|  if ( ret != ERROR_SUCCESS ) {
2192|    strcpy( type, ext );  strcat( type, "file" );
2193|    type_len = strlen( type );
2194|
2195|    ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
2196|      REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2197|    #ifdef  WINX_ENABLE_DEBUG_MODE
2198|      MARK();  WS( s );  WD( ret );
2199|    #endif
2200|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2201|    ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)type, type_len );
2202|    #ifdef  WINX_ENABLE_DEBUG_MODE
2203|      WS( type );  WD( ret );
2204|    #endif
2205|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2206|    ret = RegCloseKey( key );
2207|    #ifdef  WINX_ENABLE_DEBUG_MODE
2208|      WD( ret );
2209|    #endif
2210|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2211|  }
2212|
2213|  ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, type, 0, 0,
2214|    REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2215|  #ifdef  WINX_ENABLE_DEBUG_MODE
2216|    MARK();  WS( type );  WD( ret );
2217|  #endif
2218|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2219|
2220|  if ( explain != NULL ) {
2221|    ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)explain, strlen(explain) );
2222|    #ifdef  WINX_ENABLE_DEBUG_MODE
2223|      MARK();  WS( explain );  WD( ret );
2224|    #endif
2225|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2226|  }
2227|  if ( bDownChk )
2228|    ret = RegSetValueEx( key, "EditFlags", 0, REG_BINARY, (WinX_DataPtr)flags11, sizeof(flags11) );
2229|  else
2230|    ret = RegSetValueEx( key, "EditFlags", 0, REG_BINARY, (WinX_DataPtr)flags10, sizeof(flags10) );
2231|  #ifdef  WINX_ENABLE_DEBUG_MODE
2232|    MARK();  WD( ret );
2233|  #endif
2234|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2235|  ret = RegCloseKey( key );
2236|  #ifdef  WINX_ENABLE_DEBUG_MODE
2237|    WD( ret );
2238|  #endif
2239|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2240|
2241|  if ( iconNum != -1 ) {
2242|    sprintf( s, "%s\\DefaultIcon", type );
2243|    ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
2244|      REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2245|    #ifdef  WINX_ENABLE_DEBUG_MODE
2246|      MARK();  WS( s );  WD( ret );
2247|    #endif
2248|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2249|    sprintf( s, "%s,%d", iconPath, iconNum );
2250|    ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)s, strlen(s) );
2251|    #ifdef  WINX_ENABLE_DEBUG_MODE
2252|      WS( s );  WD( ret );
2253|    #endif
2254|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2255|    ret = RegCloseKey( key );
2256|    #ifdef  WINX_ENABLE_DEBUG_MODE
2257|      WD( ret );
2258|    #endif
2259|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2260|  }
2261|
2262|  if ( bDefault ) {
2263|    sprintf( s, "%s\\shell", type );
2264|    ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
2265|      REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2266|    #ifdef  WINX_ENABLE_DEBUG_MODE
2267|      MARK();  WS( s );  WD( ret );
2268|    #endif
2269|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2270|    ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)actionName, strlen(actionName) );
2271|    #ifdef  WINX_ENABLE_DEBUG_MODE
2272|      WS( actionName );  WD( ret );
2273|    #endif
2274|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2275|    RegCloseKey( key );
2276|    #ifdef  WINX_ENABLE_DEBUG_MODE
2277|      WD( ret );
2278|    #endif
2279|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2280|  }
2281|
2282|  sprintf( s, "%s\\shell\\%s", type, actionName );
2283|  ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
2284|    REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2285|  #ifdef  WINX_ENABLE_DEBUG_MODE
2286|    MARK();  WS( s );  WD( ret );
2287|  #endif
2288|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2289|  ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)actionTitle, strlen(actionTitle) );
2290|  #ifdef  WINX_ENABLE_DEBUG_MODE
2291|    WS( actionTitle );  WD( ret );
2292|  #endif
2293|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2294|  ret = RegSetValueEx( key, "EditFlags", 0, REG_BINARY, (WinX_DataPtr)flags2, sizeof(flags2) );
2295|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2296|  RegCloseKey( key );
2297|  #ifdef  WINX_ENABLE_DEBUG_MODE
2298|    WD( ret );
2299|  #endif
2300|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2301|
2302|  sprintf( s, "%s\\shell\\%s\\command", type, actionName );
2303|  ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
2304|    REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2305|  #ifdef  WINX_ENABLE_DEBUG_MODE
2306|    WS( s );  WD( ret );
2307|  #endif
2308|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2309|  ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)command, strlen(command) );
2310|  #ifdef  WINX_ENABLE_DEBUG_MODE
2311|    WS( command );  WD( ret );
2312|  #endif
2313|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2314|  RegCloseKey( key );
2315|  #ifdef  WINX_ENABLE_DEBUG_MODE
2316|    WD( ret );
2317|  #endif
2318|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2319|
2320|  BigStack_end();
2321|
2322|  ERRORS_FUNC_END( WinX_setExtApp );
2323|}
2324|#endif  /* USES_BIGSTACK */
2325|
2326|
2327| 
2328|/**************************************************************************
2329|  9-2. <<< [WinX_setFolderApp] フォルダをアプリケーションに関連付けする >>> 
2330|【引数】
2331|  ・char*  actionName;  アクション名(英語)
2332|  ・char*  actionTitle; アクション・表題(右クリック・メニューの項目)
2333|  ・char*  command;     アクション・コマンド、実行するアプリケーション
2334|【補足】
2335|・actionTitle に、アクセスキー(例:(&A))を指定できます。
2336|・actionName を "open" にしないと、WinX_setNewFile 関数によって、
2337|  新規作成を登録できなくなります。
2338|・command には、実行ファイルをフルパスで指定してください。
2339|***************************************************************************/
2340|#ifdef  USES_BIGSTACK
2341|void  WinX_setFolderApp( const char* actionName, const char* actionTitle,
2342|  const char* command, bool bDefault )
2343|{
2344|  HKEY  key;
2345|  LONG  ret;
2346|  static  char  flags[4] = { 0x01, 0x00, 0x00, 0x00 };
2347|  char*  s;
2348|  DWORD  dwDisp;
2349|
2350|  ERRORS_FUNC_START( WinX_setFolderApp );
2351|
2352|  BigStack_start();
2353|  s = BigStack_alloc( 2048 );
2354|
2355|  if ( bDefault ) {
2356|    ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, "Directory\\shell", 0, 0,
2357|      REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2358|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2359|    ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)actionName, strlen(actionName) );
2360|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2361|    RegCloseKey( key );
2362|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2363|  }
2364|
2365|  sprintf( s, "Directory\\shell\\%s", actionName );
2366|  ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
2367|    REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2368|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2369|  ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)actionTitle, strlen(actionTitle) );
2370|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2371|  ret = RegSetValueEx( key, "EditFlags", 0, REG_BINARY, (WinX_DataPtr)flags, sizeof(flags) );
2372|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2373|  RegCloseKey( key );
2374|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2375|
2376|  sprintf( s, "Directory\\shell\\%s\\command", actionName );
2377|  ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
2378|    REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2379|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2380|  ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)command, strlen(command) );
2381|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2382|  RegCloseKey( key );
2383|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2384|
2385|  BigStack_end();
2386|
2387|  ERRORS_FUNC_END( WinX_setFolderApp );
2388|}
2389|#endif  /* USES_BIGSTACK */
2390|
2391|
2392| 
2393|/**************************************************************************
2394|  9-3. <<< [WinX_unsetExtApp] 拡張子とアプリケーションの関連付けを解除する >>> 
2395|【引数】
2396|  ・char*  ext;         拡張子(3バイトまで)
2397|  ・char*  actionName;  アクション名(英語)
2398|【補足】
2399|・WinX_setExtApp 関数によって設定された場合のみ正しく解除します。
2400|・他のアクションがある場合、それらは残ります。
2401|***************************************************************************/
2402|#ifdef  USES_BIGSTACK
2403|void  WinX_unsetExtApp( const char* ext, const char* actionName )
2404|{
2405|  enum { type_max = 2048 };
2406|  HKEY  key;
2407|  LONG  ret;
2408|  char*  type;
2409|  char*  s;
2410|  FILETIME  time;
2411|  int  size = 2048;
2412|  int  type_len;
2413|
2414|  ERRORS_FUNC_START( WinX_unsetExtApp );
2415|
2416|  BigStack_start();
2417|  type = BigStack_alloc( type_max );
2418|  s = BigStack_alloc( size );
2419|
2420|  /* タイプ名 type を取得する */
2421|  s[0]= '.';  strcpy( s + 1, ext );
2422|  ret = RegOpenKeyEx( HKEY_CLASSES_ROOT, s, 0L, KEY_ALL_ACCESS, &key );
2423|  if ( ret == 2 )  { BigStack_end();  return; }  /* 既に関連付けが無い */
2424|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2425|  type_len = type_max;
2426|  ret = RegQueryValueEx( key, NULL, NULL, NULL, type, &type_len );
2427|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2428|  ret = RegCloseKey( key );
2429|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2430|
2431|  /* アクションを削除する */
2432|  sprintf( s, "%s\\shell\\%s\\command", type, actionName );
2433|  ret = RegDeleteKey( HKEY_CLASSES_ROOT, s );
2434|  if ( (ret & 0xFFFF) == ERROR_FILE_NOT_FOUND )  return;  /* なければ返る */
2435|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2436|
2437|  sprintf( s, "%s\\shell\\%s", type, actionName );
2438|  ret = RegDeleteKey( HKEY_CLASSES_ROOT, s );
2439|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2440|
2441|  /* open アクションをデフォルトに戻す */
2442|  sprintf( s, "%s\\shell", type );
2443|  ret = RegOpenKeyEx( HKEY_CLASSES_ROOT, s, 0L, KEY_ALL_ACCESS, &key );
2444|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2445|  ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)"open", 4 );
2446|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2447|  RegCloseKey( key );
2448|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2449|
2450|  /* 他のアクションがあるかどうか調べる */
2451|  sprintf( s, "%s\\shell", type );
2452|  ret = RegOpenKeyEx( HKEY_CLASSES_ROOT, s, 0L, KEY_ALL_ACCESS, &key );
2453|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2454|
2455|  /* 他のアクションが無ければ、ファイルタイプを削除する */
2456|  ret = RegEnumKeyEx( key, 0, s, &size, NULL, NULL, NULL, &time );
2457|  if ( ret == ERROR_NO_MORE_ITEMS ) {
2458|    sprintf( s, "%s\\shell", type );
2459|    ret = RegDeleteKey( HKEY_CLASSES_ROOT, s );
2460|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2461|
2462|    sprintf( s, "%s\\DefaultIcon", type );
2463|    ret = RegDeleteKey( HKEY_CLASSES_ROOT, s );
2464|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2465|
2466|    ret = RegDeleteKey( HKEY_CLASSES_ROOT, type );
2467|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2468|
2469|    s[0]= '.';  strcpy( s + 1, ext );
2470|    ret = RegDeleteKey( HKEY_CLASSES_ROOT, s );
2471|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2472|  }
2473|  else if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2474|
2475|  BigStack_end();
2476|
2477|  ERRORS_FUNC_END( WinX_unsetExtApp );
2478|}
2479|#endif  /* USES_BIGSTACK */
2480|
2481|
2482| 
2483|/**************************************************************************
2484|  9-4. <<< [WinX_unsetFolderApp] フォルダとアプリケーションの関連付けを解除する >>> 
2485|【引数】
2486|  ・char*  actionName;  アクション名(英語)
2487|【補足】
2488|・WinX_setFolderApp 関数によって設定された場合のみ正しく解除します。
2489|***************************************************************************/
2490|#ifdef  USES_BIGSTACK
2491|void  WinX_unsetFolderApp( const char* actionName )
2492|{
2493|  LONG  ret;
2494|  char*  s;
2495|  int  size = 2048;
2496|
2497|  ERRORS_FUNC_START( WinX_unsetFolderApp );
2498|
2499|  BigStack_start();
2500|  s = BigStack_alloc( size );
2501|
2502|  /* アクションを削除する */
2503|  sprintf( s, "Directory\\shell\\%s\\command", actionName );
2504|  ret = RegDeleteKey( HKEY_CLASSES_ROOT, s );
2505|  if ( (ret & 0xFFFF) == ERROR_FILE_NOT_FOUND )  return;  /* なければ返る */
2506|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2507|
2508|  sprintf( s, "Directory\\shell\\%s", actionName );
2509|  ret = RegDeleteKey( HKEY_CLASSES_ROOT, s );
2510|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2511|
2512|  BigStack_end();
2513|
2514|  ERRORS_FUNC_END( WinX_unsetFolderApp );
2515|}
2516|#endif  /* USES_BIGSTACK */
2517|
2518|
2519| 
2520|/**************************************************************************
2521|  9-5. <<< [WinX_setNewFile] 右クリックの新規作成に登録する >>> 
2522|【引数】
2523|  ・char*  ext;        拡張子(3バイトまで)
2524|  ・char*  newFName;   デフォルト・ファイルの名前(NULL 可)(補足参照)
2525|【補足】
2526|・ext には、WinX_setExtApp 関数でアプリケーションに関連付けした拡張子を
2527|  指定します。
2528|・WinX_setExtApp 関数で指定した actionName 引数は "open" にしてください。
2529|・newFName は、新規作成するときに作られるデータの入ったファイルの
2530|  ファイル名を指定します。ただし、Windows\ShellNew フォルダ
2531|  (WinX_getShellNewPath 関数で取得できます)に
2532|  FileX_copy 関数などを用いてそのファイルを入れてください。
2533|  newFName に NULL を指定すると、空(0バイト)のデータを作成するように
2534|  設定します。
2535|・右クリックメニューに表示される項目は、WinX_setExtApp 関数の explain
2536|  引数に指定したものを表示します。
2537|【参考】
2538|・http://www.saitou.com/windows/doc/dsk0001.htm
2539|***************************************************************************/
2540|#if defined(USES_FILEX) && defined(USES_BIGSTACK) && defined(USES_EXCEPT3)
2541|void  WinX_setNewFile( const char* ext, const char* newFName )
2542|{
2543|  HKEY  key;
2544|  LONG  ret;
2545|  char*  s;
2546|  DWORD  dwDisp;
2547|
2548|  ERRORS_FUNC_START( WinX_setNewFile );
2549|
2550|  BigStack_start();
2551|  s = BigStack_alloc( 2048 );
2552|
2553|  if ( newFName == NULL ) {
2554|
2555|    sprintf( s, ".%s\\ShellNew", ext );
2556|    ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
2557|      REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2558|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2559|    ret = RegSetValueEx( key, "NullFile", 0, REG_SZ, "", 0 );
2560|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2561|    ret = RegCloseKey( key );
2562|
2563|  }
2564|  else {
2565|    strcpy( s, WinX_getShellNewPath() );
2566|    StrX_addFName( s, newFName );
2567|    if ( ! FileX_isExist( s ) )
2568|      error2_1( Errors_Unofficial, "file not found in ShellNew Folder or new file (%s)", s );
2569|
2570|    sprintf( s, ".%s\\ShellNew", ext );
2571|    ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
2572|      REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2573|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2574|    ret = RegSetValueEx( key, "FileName", 0, REG_SZ, newFName, strlen(newFName) );
2575|    if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2576|    ret = RegCloseKey( key );
2577|
2578|  }
2579|  BigStack_end();
2580|
2581|  ERRORS_FUNC_END( WinX_setNewFile );
2582|}
2583|#endif
2584|
2585| 
2586|/**************************************************************************
2587|  9-6. <<< [WinX_unsetNewFile] 右クリックの新規作成から外す >>> 
2588|【引数】
2589|  ・char*  ext;        拡張子(3バイトまで)
2590|【補足】
2591|・ext には、アプリケーションに関連付け去れている拡張子のみ指定できます。
2592|・WinX_setNewFile 関数で設定したタイプのみ正常に動作します。
2593|***************************************************************************/
2594|#ifdef  USES_BIGSTACK
2595|void  WinX_unsetNewFile( const char* ext )
2596|{
2597|  LONG  ret;
2598|  char*  s;
2599|
2600|  ERRORS_FUNC_START( WinX_unsetNewFile );
2601|
2602|  BigStack_start();
2603|  s = BigStack_alloc( 2048 );
2604|
2605|  sprintf( s, ".%s\\ShellNew", ext );
2606|  ret = RegDeleteKey( HKEY_CLASSES_ROOT, s );
2607|  if ( (ret & 0xFFFF) != ERROR_FILE_NOT_FOUND &&
2608|        ret != ERROR_SUCCESS )  WinX_throw( ret );
2609|
2610|  BigStack_end();
2611|
2612|  ERRORS_FUNC_END( WinX_unsetNewFile );
2613|}
2614|#endif
2615| 
2616|/**************************************************************************
2617|  9-7. <<< [WinX_isNeedSecurity] ダウンロード時に開く確認をするかどうかを返す >>> 
2618|【引数】
2619|  ・char*  ext;     拡張子
2620|  ・bool  返り値;   確認をするかどうか
2621|【補足】
2622|・レジストリに登録されていない拡張子を指定したときは、true を返します。
2623|***************************************************************************/
2624|#if defined(USES_EXCEPT3)
2625|bool  WinX_isNeedSecurity( const char* ext )
2626|{
2627|  bool  r;
2628|  HKEY  key;
2629|  char  s1[256];
2630|  char  s2[256];
2631|  DWORD type;
2632|  DWORD size;
2633|  LONG  ret;
2634|
2635|  ERRORS_FUNC_START( WinX_isNeedSecurity );
2636|
2637|  c_try {
2638|    s2[0] = '.';  strcpy( s2 + 1, ext );
2639|    WinX_getReg_s( HKEY_CLASSES_ROOT, s2, NULL, s1, sizeof(s1) );
2640|    ret = RegOpenKeyEx( HKEY_CLASSES_ROOT, s1, 0L, KEY_READ, &key );
2641|    if ( ret != ERROR_SUCCESS ) {
2642|      r = true;
2643|    }
2644|    else {
2645|      size = sizeof(s2);
2646|      ret = RegQueryValueEx( key, "EditFlags", NULL, &type, s2, &size );
2647|      if ( ret != ERROR_SUCCESS || *s2 == '\0' )
2648|        r = true;
2649|      else
2650|        r = ! s2[2];
2651|    }
2652|    RegCloseKey( key );
2653|  }
2654|  c_catch ( Errors_Msg*, msg ) {
2655|    if ( msg->code == WinX_Err_NoRegKey )
2656|      r = true;
2657|  } c_end_catch;
2658|
2659|  ERRORS_FUNC_END( WinX_isNeedSecurity );
2660|  return  r;
2661|}
2662|#endif
2663| 
2664|/**************************************************************************
2665|  9-8. <<< [WinX_getShellNewPath] 新規作成用フォルダのパスを返す >>> 
2666|【補足】
2667|・新規作成時に参照するテンプレートファイルの入ったフォルダのパスを
2668|  返します。
2669|***************************************************************************/
2670|char*  WinX_getShellNewPath()
2671|{
2672|  static unsigned char  var[_MAX_PATH];
2673|  unsigned long  size = sizeof(var);
2674|  HKEY  key;
2675|  LONG  ret;
2676|
2677|  ERRORS_FUNC_START( WinX_getShellNewPath );
2678|
2679|  ret = RegOpenKeyEx( HKEY_CURRENT_USER,
2680|    "Software\\Microsoft\\Windows\\CurrentVersion\\"
2681|    "Explorer\\Shell Folders", 0L, KEY_READ, &key );
2682|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2683|
2684|  ret = RegQueryValueEx( key, "Templates", NULL, NULL, var, &size );
2685|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2686|
2687|  RegCloseKey( key );
2688|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2689|
2690|  ERRORS_FUNC_END( WinX_getShellNewPath );
2691|  return  (char*)var;
2692|}
2693|
2694|
2695| 
2696|/**************************************************************************
2697|  9-9. <<< [WinX_setIcon] ファイルタイプに関連したアイコンを登録する >>> 
2698|【引数】
2699|  ・char*  ext;         拡張子(ピリオド不要)
2700|  ・char*  path;        アイコンファイルのパス
2701|  ・int    iIcon;       アイコンファイル中のアイコン番号(0〜)
2702|***************************************************************************/
2703|void  WinX_setIcon( const char* ext, const char* path, int iIcon )
2704|{
2705|  HKEY  key;
2706|  char  s[256];
2707|  char  type[256];
2708|  int   type_len;
2709|  LONG  ret;
2710|  DWORD  dwDisp;
2711|
2712|  ERRORS_FUNC_START( WinX_setIcon );
2713|
2714|  strcpy( s, "." );  strcat( s, ext );
2715|  ret = RegOpenKeyEx( HKEY_CLASSES_ROOT, s, 0L, KEY_READ, &key );
2716|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2717|  type_len = sizeof(type);
2718|  ret = RegQueryValueEx( key, NULL, NULL, NULL, type, &type_len );
2719|  if ( ret != ERROR_SUCCESS || type[0] == '\0' )  WinX_throw( ret );
2720|  ret = RegCloseKey( key );
2721|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2722|
2723|  sprintf( s, "%s\\DefaultIcon", type );
2724|  ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
2725|    REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
2726|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2727|  sprintf( s, "%s,%d", path, iIcon );
2728|  ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)s, strlen(s) );
2729|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2730|  ret = RegCloseKey( key );
2731|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2732|
2733|  ERRORS_FUNC_END( WinX_setIcon );
2734|}
2735|
2736| 
2737|/**************************************************************************
2738|  9-10. <<< [WinX_getIcon] ファイルタイプに関連しているアイコンを取得する >>> 
2739|【引数】
2740|  ・char*  ext;         拡張子(ピリオド不要)
2741|  ・char*  path;        アイコンファイルのパス
2742|  ・int*   iIcon;       アイコンファイル中のアイコン番号(0〜)を格納するアドレス
2743|【補足】
2744|・取得したアイコンは、ピクチャーコントロールのタイプをアイコンにして、
2745|  ExtractIconEx, CStatic::SetIcon を使って表示できます。
2746|・アイコンが登録されていない場合、path="", iIcon=0 になります。
2747|***************************************************************************/
2748|#ifdef  USES_EXCEPT3
2749|#ifdef  USES_FILEX
2750|void  WinX_getIcon( const char* ext, char* path, int* iIcon )
2751|{
2752|  HKEY  key;
2753|  char  s[256];
2754|  char  s2[256];
2755|  char  type[256];
2756|  int   len;
2757|  char* p;
2758|  LONG  ret;
2759|  bool  bExeDefIcon = false;
2760|
2761|  ERRORS_FUNC_START( WinX_getIcon );
2762|
2763|  c_try {
2764|
2765|    strcpy( s, "." );  strcat( s, ext );
2766|    ret = RegOpenKeyEx( HKEY_CLASSES_ROOT, s, 0L, KEY_READ, &key );
2767|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2768|    len = sizeof(type);
2769|    ret = RegQueryValueEx( key, NULL, NULL, NULL, type, &len );
2770|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2771|    type[len] = '\0';
2772|    ret = RegCloseKey( key );
2773|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2774|
2775|    /* DefaultIcon からアイコンのパスを取得する */
2776|    sprintf( s, "%s\\DefaultIcon", type );
2777|    ret = RegOpenKeyEx( HKEY_CLASSES_ROOT, s, 0L, KEY_READ, &key );
2778|
2779|    if ( ret == 2 )  bExeDefIcon = true;
2780|    else if ( ret != ERROR_SUCCESS ) { WinX_throw( ret ); }
2781|    else {
2782|      ret = RegQueryValueEx( key, NULL, NULL, NULL, type, &len );
2783|      len = sizeof(s);
2784|      ret = RegQueryValueEx( key, NULL, NULL, NULL, s, &len );
2785|      if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
2786|      p = StrX_RSearchC2( s, ',' );
2787|      if ( p == NULL )
2788|        { strcpy( path, s );  *iIcon = 0; }
2789|      else
2790|        { *p = '\0';  strcpy( path, s );  *iIcon = atoi( p + 1 ); }
2791|
2792|      ret = RegCloseKey( key );
2793|      if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
2794|    }
2795|
2796|    /* Command からアイコンのパスを取得する */
2797|    if ( bExeDefIcon ) {
2798|      sprintf( s, "%s\\Shell", type );
2799|      WinX_getReg_s( HKEY_CLASSES_ROOT, s, NULL, s2, sizeof(s2) );
2800|      sprintf( s, "%s\\Shell\\%s\\command", type, s2 );
2801|      WinX_getReg_s( HKEY_CLASSES_ROOT, s, NULL, s2, sizeof(s2) );
2802|      StrX_getSpacedPath( s2, path, NULL );
2803|      *iIcon = 0;
2804|    }
2805|  }
2806|  c_catch ( Errors_Msg*, msg ) {
2807|    if ( ret == 2 )
2808|      { path[0] = '\0';  iIcon = 0; }
2809|    else  c_throw_again();
2810|  } c_end_catch;
2811|
2812|  ERRORS_FUNC_END( WinX_getIcon );
2813|}
2814|#endif
2815|#endif
2816| 
2817|/**************************************************************************
2818|  9-11. <<< [WinX_getFTypeInfos] レジストリにある拡張子に関する情報を得る >>> 
2819|【引数】
2820|  ・WinX_FType*  types;   格納する配列領域の先頭アドレス
2821|  ・int   types_size;     types のメモリサイズ
2822|  ・bool  bAll;           全拡張子に対する情報も加えるか
2823|  ・WinX_FType** defType; 左ダブルクリックしたときに実行されるアクション(ポインタのアドレス)
2824|  ・int  返り値;          types に格納した配列要素数
2825|【補足】
2826|・エクスプローラでファイルを右クリックしたときに表示されるメニュー項目、
2827|  つまり、レジストリの HKEY_CLASSES_ROOT\(ext)\shell にある情報を取得します。
2828|***************************************************************************/
2829|#if defined(USES_EXCEPT3)
2830|int  WinX_getFTypeInfos( const char* ext, WinX_FType* types, int types_size,
2831|  bool bAll, WinX_FType** defType )
2832|{
2833|  int   i, j;
2834|  int   nSkip;
2835|  HKEY  shellKey;
2836|  char  subKeyPath[256];
2837|  char  typeRootName[256];
2838|  char  defName[64];
2839|  DWORD type;
2840|  LONG  ret;
2841|  DWORD size;
2842|
2843|  ERRORS_FUNC_START( WinX_getFTypeInfos );
2844|
2845|  i = 0;
2846|  nSkip = 0;
2847|  *defType = NULL;
2848|
2849|  c_try {
2850|
2851|    if ( bAll ) {
2852|
2853|      /* HKEY_CLASSES_ROOT\*\shell キーを shellKey に */
2854|      ret = RegOpenKeyEx( HKEY_CLASSES_ROOT, "*\\shell", 0L, KEY_READ, &shellKey );
2855|      if ( ret != ERROR_SUCCESS )
2856|        { error2_0( WinX_Err_NoRegKey, "" ); }
2857|
2858|      /* HKEY_CLASSES_ROOT\*\shell\標準 の値を defName に */
2859|      size = sizeof(defName);
2860|      ret = RegQueryValueEx( shellKey, NULL, NULL, &type, defName, &size );
2861|      if ( ret != ERROR_SUCCESS )  defName[0] = '\0';
2862|
2863|      for ( j = 0; ; j++ ) {
2864|        WinX_FType*  type = &types[i + j - nSkip];
2865|
2866|        switch ( WinX_getFTypeInfos_sub( shellKey, j, type ) ) {
2867|          case  0:  break;
2868|          case  1:  goto exit_for2;
2869|          case  2:  nSkip++;  break;
2870|        }
2871|
2872|        if ( strcmp( type->name, defName ) == 0 ) {
2873|          /* リストの先頭へ持っていく */
2874|          WinX_FType  t = *type;
2875|          memmove( &types[1], &types[0], sizeof(WinX_FType) * (i + j - nSkip) );
2876|          types[0] = t;
2877|
2878|          if ( *defType == NULL )
2879|            *defType = &types[0];
2880|        }
2881|      }
2882|     exit_for2:
2883|      RegCloseKey( shellKey );
2884|      i += j;
2885|    }
2886|  }
2887|  c_catch ( Errors_Msg*, msg ) {
2888|    if ( msg->code != WinX_Err_NoRegKey )  c_throw_again();
2889|  } c_end_catch;
2890|
2891|  c_try {
2892|
2893|    /* HKEY_CLASSES_ROOT\.(ext)\標準 の値を typeRootName に */
2894|    if ( ext[0] == '\0' || strcmp( ext, "*" ) == 0 ) {
2895|      strcpy( typeRootName, "*" );
2896|      bAll = false;
2897|    }
2898|    else {
2899|      subKeyPath[0] = '.';  strcpy( subKeyPath + 1, ext );
2900|      WinX_getReg_s( HKEY_CLASSES_ROOT, subKeyPath, NULL, typeRootName, sizeof(typeRootName) );
2901|    }
2902|
2903|    /* HKEY_CLASSES_ROOT\(typeRootName)\shell キーを shellKey に */
2904|    sprintf( subKeyPath, "%s\\shell", typeRootName );
2905|    ret = RegOpenKeyEx( HKEY_CLASSES_ROOT, subKeyPath, 0L, KEY_READ, &shellKey );
2906|    if ( ret != ERROR_SUCCESS )
2907|      { error2_0( WinX_Err_NoRegKey, "" ); }
2908|
2909|    /* HKEY_CLASSES_ROOT\(typeRootName)\shell\標準 の値を defName に */
2910|    size = sizeof(defName);
2911|    ret = RegQueryValueEx( shellKey, NULL, NULL, &type, defName, &size );
2912|    if ( ret != ERROR_SUCCESS )  defName[0] = '\0';
2913|
2914|    for ( j = 0; ; j++ ) {
2915|      WinX_FType*  type = &types[i + j - nSkip];
2916|
2917|      switch ( WinX_getFTypeInfos_sub( shellKey, j, type ) ) {
2918|        case  0:  break;
2919|        case  1:  goto exit_for;
2920|        case  2:  nSkip++;  break;
2921|      }
2922|
2923|      if ( strcmp( type->name, defName ) == 0 || stricmp( type->name, "open" ) == 0 ) {
2924|        /* リストの先頭へ持っていく */
2925|        WinX_FType  t = *type;
2926|        memmove( &types[1], &types[0], sizeof(WinX_FType) * (i + j - nSkip) );
2927|        types[0] = t;
2928|
2929|        if ( *defType == NULL )
2930|          *defType = &types[0];
2931|      }
2932|    }
2933|   exit_for:
2934|    RegCloseKey( shellKey );
2935|    i += j;
2936|  }
2937|  c_catch ( Errors_Msg*, msg ) {
2938|    if ( msg->code != WinX_Err_NoRegKey )  c_throw_again();
2939|  } c_end_catch;
2940|
2941|
2942|  i -= nSkip;
2943|  ASSERT( *defType != NULL || i == 0 );
2944|
2945|  ERRORS_FUNC_END( WinX_getFTypeInfos );
2946|  return  i;
2947|}
2948|#endif
2949|
2950|/**************************************************************************
2951|*  9-12. <<< [WinX_getFTypeInfos_sub] WinX_getFTypeInfos のサブルーチン >>>
2952|*【引数】
2953|*  ・HKEY  shellKey;      HKEY_CLASSES_ROOT\(typeRootName)\shell のキー
2954|*  ・int   iSubKey;       shellKey のサブキー番号(0〜返り値が1になるまで)
2955|*  ・WinX_FType*  type;   格納する領域の先頭アドレス
2956|*  ・int  返り値;         0=成功、1=iSubKey が大きすぎる、2=type に格納する情報が無い
2957|***************************************************************************/
2958|#if defined(USES_EXCEPT3)
2959|int  WinX_getFTypeInfos_sub( HKEY shellKey, int iSubKey, WinX_FType* type )
2960|{
2961|  DWORD size, size2;
2962|  LONG  ret;
2963|  FILETIME  time;
2964|  char  className[256];
2965|  char  subKeyPath[256];
2966|
2967|  /* HKEY_CLASSES_ROOT\(typeRootName)\shell のサブキー名を type->name に */
2968|  size = sizeof(type->name);
2969|  size2 = sizeof(className);
2970|  ret = RegEnumKeyEx( shellKey, iSubKey, type->name, &size, NULL,
2971|    className, &size2, &time );
2972|  if ( ret == ERROR_NO_MORE_ITEMS )  return  1;
2973|
2974|  /* HKEY_CLASSES_ROOT\(typeRootName)\shell\(name)\標準 の値を type->caption に */
2975|  c_try {
2976|    type->caption[0] = '\0';
2977|    WinX_getReg_s( shellKey, type->name, NULL,
2978|          type->caption, sizeof(type->caption) );
2979|  }
2980|  Errors_ignore_catch( case WinX_Err_NoRegData: );
2981|  if ( type->caption[0] == '\0' ) {
2982|    if ( stricmp( type->name, "open" ) == 0 )
2983|      strcpy( type->caption, "開く(&O)" );
2984|    else if ( stricmp( type->name, "print" ) == 0 )
2985|      strcpy( type->caption, "印刷(&P)" );
2986|    else
2987|      StrX_cpy( type->caption, type->name, sizeof( type->caption ) );
2988|  }
2989|
2990|  /* HKEY_CLASSES_ROOT\(typeRootName)\shell\(name)\EditFlags の値を type->editFlags に */
2991|  c_try {
2992|    WinX_getReg_x( shellKey, type->name, "EditFlags",
2993|      &type->editFlags, sizeof(type->editFlags) );
2994|  }
2995|  Errors_ignore_catch( case WinX_Err_NoRegData: );
2996|
2997|  /* HKEY_CLASSES_ROOT\(typeRootName)\shell\(name)\command\標準 の値を type->command に */
2998|  {
2999|    bool  bGet = false;
3000|    c_try {
3001|      sprintf( subKeyPath, "%s\\command", type->name );
3002|      WinX_getReg_s( shellKey, subKeyPath, NULL,
3003|        type->command, sizeof(type->command) );
3004|      bGet = true;
3005|    }
3006|    c_catch( Errors_Msg*, msg ) {
3007|    } c_end_catch;
3008|    if ( ! bGet )  return  2;
3009|  }
3010|
3011|  /* HKEY_CLASSES_ROOT\(typeRootName)\shell\(name)\ddeExec\標準 の値を type->ddeMsg に */
3012|  type->bDDE = false;
3013|  c_try {
3014|    sprintf( subKeyPath, "%s\\ddeExec", type->name );
3015|    WinX_getReg_s( shellKey, subKeyPath, NULL,
3016|      type->ddeMsg, sizeof(type->ddeMsg) );
3017|    sprintf( subKeyPath, "%s\\ddeExec\\application", type->name );
3018|    WinX_getReg_s( shellKey, subKeyPath, NULL,
3019|      type->ddeApp, sizeof(type->ddeApp) );
3020|    sprintf( subKeyPath, "%s\\ddeExec\\ifexec", type->name );
3021|    WinX_getReg_s( shellKey, subKeyPath, NULL,
3022|      type->ddeOpenCmd, sizeof(type->ddeOpenCmd) );
3023|    sprintf( subKeyPath, "%s\\ddeExec\\topic", type->name );
3024|    WinX_getReg_s( shellKey, subKeyPath, NULL,
3025|      type->ddeTopic, sizeof(type->ddeTopic) );
3026|    type->bDDE = true;
3027|  }
3028|  c_catch( Errors_Msg*, msg ) {
3029|  } c_end_catch;
3030|
3031|  return 0;
3032|}
3033|#endif
3034| 
3035|/*------------------------------------------------------------------------*/
3036|/*  10. <<<< ◆ インストール関係 >>>> */ 
3037|/*------------------------------------------------------------------------*/
3038|
3039|
3040| 
3041|/**************************************************************************
3042|  10-1. <<< [WinX_uninstallFolder] アンインストーラのあるフォルダを削除する >>> 
3043|【引数】
3044|  ・char*  folderPath;  削除するフォルダのパス
3045|  ・char*  appName;     アプリケーション名(ダイアログのタイトルに表示します)
3046|  ・char*  folderName;  削除するフォルダ名(誤った削除をしないため)
3047|【補足】
3048|・削除するフォルダのバックアップを取っておいて下さい。
3049|・アプリが終了する直前に実行してください。終了してから削除します。
3050|・WSH がある時は、それを使用して自動的に削除します(完了メッセージあり)。
3051|  WSH が無いときは、削除するフォルダを開き、ユーザに削除するように
3052|  メッセージを表示します。
3053|・folderName は、誤って別のフォルダを削除しないために用意しています。
3054|  folderPath は、実行ファイルのパスなどから導いたものに対して、
3055|  folderName は、アプリケーションのコードでダイレクトに文字列を指定します。
3056|・完全にフォルダが削除されるまで、フォルダの削除を何度もトライします。
3057|  そのため、早いうちに、実行ファイルの実行を終了するようにしてください。
3058|***************************************************************************/
3059|
3060|#if defined(USES_FILEX) && defined(USES_STRX) && defined(USES_EXCEPT3)
3061|bool  WinX_uninstallFolder( const char* folderPath, const char* appName,
3062|  const char* folderName )
3063|{
3064|  FILE*  f;
3065|  char  path[_MAX_PATH];
3066|  char  path2[_MAX_PATH];
3067|  char  s[_MAX_PATH*2];
3068|  char*  wshPath = WinX_getWSHPath();
3069|
3070|  ERRORS_FUNC_START( WinX_uninstallFolder );
3071|
3072|  if ( wshPath == NULL ) {
3073|    MessageBox( NULL, "アンインストールが完了しました。\r\n\r\n"
3074|      "ただし、実行ファイルのある(次に表示される)フォルダは、"
3075|      "手動で削除してください。", "アンインストール完了", MB_OK );
3076|    WinX_openExplorer( folderPath );
3077|  }
3078|  else if ( stricmp( StrX_refFName( folderPath ), folderName ) != 0 ) {
3079|    sprintf( s, "アンインストールが完了しました。\r\n\r\n"
3080|      "ただし、削除するフォルダ名が、アプリケーションが想定した名前(%s)"
3081|      "と異なるため削除しませんでした。\r\n"
3082|      "次に表示されるフォルダを確認して、手動で削除してください。", folderName );
3083|    MessageBox( NULL, s, "アンインストール完了", MB_OK );
3084|    WinX_openExplorer( folderPath );
3085|  }
3086|  else {
3087|    #ifndef  NDEBUG
3088|      sprintf( s, "フォルダ %s を削除します。よろしいですか?", folderPath );
3089|      if ( MessageBox( NULL, s, "デバッグ版専用メッセージ", MB_YESNO ) == IDNO )
3090|        return  false;
3091|    #endif
3092|
3093|    StrX_cpyAbsPath( path, "uninst.vbs", _MAX_PATH - 1, WinX_getTempPath() );
3094|    f = FileX_open( path, "wt" );
3095|
3096|    fputs( "Set fs = CreateObject( \"Scripting.FileSystemObject\" )\n", f );
3097|    fputs( "On Error Resume Next\n", f );
3098|    fputs( "Dim I\n", f );
3099|    fputs( "I = 0\n", f );
3100|    fputs( "Do\n", f );
3101|    fputs( "  Err.Clear\n", f );
3102|    fprintf( f, "  fs.DeleteFolder \"%s\", True\n", folderPath );
3103|    fputs( "  If Err.Number = 76 Then\n", f );
3104|    fprintf( f, "    MsgBox \"パスの指定が間違っています : %s\"\n", folderPath );
3105|    fputs( "  End If\n", f );
3106|    fputs( "  If Err.Number = 70 Then\n", f );
3107|    fputs( "    I = I+ 1\n", f );
3108|    fputs( "    If I = 2000 Then\n", f );
3109|    fprintf( f, "      If MsgBox( \"削除が拒否されました。"
3110|      "%s の中にあるファイルかプロンプトを閉じて「再試行」を押してください。\","
3111|      "vbRetryCancel + vbExclamation, \"アンインストール - %s\" )"
3112|      " = vbCancel Then\n",
3113|      folderPath, appName );  /* インストーラが終わっていない可能性があります */
3114|    fputs( "        Exit Do\n", f );
3115|    fputs( "      End If\n", f );
3116|    fputs( "      I = 0\n", f );
3117|    fputs( "    End If\n", f );
3118|    fputs( "  End If\n", f );
3119|    fputs( "Loop While Err.Number = 70\n", f );
3120|    fputs( "If Err.Number = 0 Then\n", f );
3121|    fprintf( f, "  MsgBox \"アンインストールが完了しました。\", vbOKOnly, "
3122|      "\"アンインストール - %s\"\n", appName );
3123|    fputs( "Else\n", f );
3124|    fprintf( f, "  MsgBox \"アンインストールは正常に完了しませんでした。\", vbOKOnly, "
3125|      "\"アンインストール - %s\"\n", appName );
3126|    fputs( "End If\n", f );
3127|    fprintf( f, "fs.DeleteFile \"%s\", True\n", path );
3128|
3129|    fclose( f );
3130|
3131|    StrX_cpyFolder( path2, wshPath );
3132|    _chdir( path2 );
3133|    sprintf( s, "%s \"%s\"", wshPath, path );
3134|    WinExec( s, SW_SHOWNORMAL );
3135|  }
3136|
3137|  ERRORS_FUNC_END( WinX_uninstallFolder );
3138|  return  true;
3139|}
3140|#endif
3141| 
3142|/**************************************************************************
3143|  10-2. <<< [WinX_setAppUninstall] アプリケーションの追加と削除に追加する >>> 
3144|【引数】
3145|  ・char*  appName;   アプリ名(識別子)
3146|  ・char*  title;     アプリのリスト中に表示される内容
3147|  ・char*  command;   選択されたときのコマンド(アンインストーラのファイル名))
3148|***************************************************************************/
3149|void  WinX_setAppUninstall( const char* appName,
3150|  const char* title, const char* command )
3151|{
3152|  static unsigned char  s[_MAX_PATH];
3153|  HKEY  key;
3154|  LONG  ret;
3155|  DWORD  dwDisp;
3156|
3157|  ERRORS_FUNC_START( WinX_setAppUninstall );
3158|
3159|  sprintf( s, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s",
3160|    appName );
3161|  ret = RegCreateKeyEx( HKEY_LOCAL_MACHINE, s, 0, 0,
3162|    REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
3163|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3164|  ret = RegSetValueEx( key, "DisplayName", 0, REG_SZ,
3165|    (WinX_DataPtr)title, strlen(title) );
3166|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3167|  ret = RegSetValueEx( key, "UninstallString", 0, REG_SZ,
3168|    (WinX_DataPtr)command, strlen(command) );
3169|  if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3170|  ret = RegCloseKey( key );
3171|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
3172|
3173|  ERRORS_FUNC_END( WinX_setAppUninstall );
3174|}
3175|
3176|
3177| 
3178|/**************************************************************************
3179|  10-3. <<< [WinX_unsetAppUninstall] アプリケーションの追加と削除から削除する >>> 
3180|【引数】
3181|  ・char*  appName;   アプリ名(識別子)
3182|***************************************************************************/
3183|void  WinX_unsetAppUninstall( const char* appName )
3184|{
3185|  static unsigned char  s[_MAX_PATH];
3186|  LONG  ret;
3187|
3188|  ERRORS_FUNC_START( WinX_unsetAppUninstall );
3189|
3190|  sprintf( s, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s",
3191|    appName );
3192|  ret = RegDeleteKey( HKEY_LOCAL_MACHINE, s );
3193|  if ( (ret & 0xFFFF) == ERROR_FILE_NOT_FOUND )  return;  /* なければ返る */
3194|  if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
3195|
3196|  ERRORS_FUNC_END( WinX_unsetAppUninstall );
3197|}
3198|
3199|
3200| 
3201|/**************************************************************************
3202|  10-4. <<< [WinX_isSetAppUninstall] アプリケーションの追加と削除に登録されているか >>> 
3203|【引数】
3204|  ・char*  appName;   アプリ名(識別子)
3205|  ・bool  返り値;     アプリケーションの追加と削除に登録されているかどうか
3206|***************************************************************************/
3207|bool  WinX_isSetAppUninstall( const char* appName )
3208|{
3209|  char  s[_MAX_PATH];
3210|  bool  r;
3211|
3212|  ERRORS_FUNC_START( WinX_unsetAppUninstall );
3213|
3214|  sprintf( s, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s",
3215|    appName );
3216|
3217|  r = WinX_isExistReg( HKEY_LOCAL_MACHINE, s, true, false )
3218|
3219|  ERRORS_FUNC_END( WinX_unsetAppUninstall );
3220|  return  r;
3221|}
3222|
3223|
3224| 
3225|/**************************************************************************
3226|  10-5. <<< [WinX_throwToTrash] ファイルをごみ箱へ移動する >>> 
3227|***************************************************************************/
3228|void  WinX_throwToTrash( HWND hWnd, const char* path )
3229|{
3230|  SHFILEOPSTRUCT  s;
3231|
3232|  memset( &s, 0, sizeof(s) );
3233|  s.hwnd = hWnd;
3234|  s.wFunc = FO_DELETE;
3235|  s.pFrom = path;
3236|  s.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION;
3237|  s.fAnyOperationsAborted = TRUE;
3238|
3239|  ((char*)path)[ strlen(path) + 1 ] = '\0';
3240|
3241|  SHFileOperation( &s );
3242|}
3243| 
3244|/*------------------------------------------------------------------------*/
3245|/*  11. <<<< ◆(WinX_Inst) インストール関係 >>>> */ 
3246|/*------------------------------------------------------------------------*/
3247|
3248|void  WinX_RegNest_add( WinX_RegNest* );
3249|
3250| 
3251|/**************************************************************************
3252|  11-1. <<< [WinX_Inst_install] レジストリ情報をインストールする >>> 
3253|【引数】
3254|  ・WinX_Inst*  m;  インストール情報
3255|  ・char*  exePath;    メインとなる実行ファイルの絶対パス
3256|  ・bool*  enables;    拡張子別インストール許可・不許可(NULL=全部許可)
3257|  ・bool bSplitByVer;  複数のバージョンを同居させるかどうか(現在falseのみ可)
3258|【補足】
3259|・(未対応)旧 open があれば、それを open2 にして、open を追加する
3260|・アンインストール情報:.(ext)\backup = .(ext) のバックアップ
3261|・(未対応)マージ・インストール, バージョンマージインストール or 修復
3262|・(未対応)(ext)file\shell\(各アプリ最初のコマンド)\DefCmd にバックアップ
3263|・(未対応)(ext)file\shell\(各アプリ最初のコマンド)\DefaultIcon にバックアップ
3264|***************************************************************************/
3265|#ifdef  USES_BIGSTACK
3266|void  WinX_Inst_install( WinX_Inst* m, const char* exePath, bool* enables,
3267|  bool bSplitByVer )
3268|{
3269|  WinX_InstType*  type;
3270|  WinX_InstCmd*   cmd;
3271|  int   typeKeyName_len;
3272|  LONG  ret;
3273|  HKEY  key;
3274|  char  s[256];
3275|  char  typeKeyName[256];
3276|  WinX_RegData  data;
3277|  char  x[256];
3278|  int  len;
3279|  int  typeTmp;
3280|  DWORD  dwDisp;
3281|
3282|  ERRORS_FUNC_START( WinX_Inst_install );
3283|
3284|  ASSERT( ! bSplitByVer );
3285|  WinX_RegData_init( &data, x, sizeof(x) );
3286|
3287|  /* WinX_InstType の設定をレジストリに設定する */
3288|  for ( type = m->types; strcmp( type->ext, "NULL" ) != 0; type++ ) {
3289|
3290|    if ( enables != NULL && ! enables[ type - m->types ] )
3291|      continue;
3292|
3293|    if ( strcmp( type->ext, "*" ) == 0 || stricmp( type->ext, "folder" ) == 0 ) {
3294|      strcpy( typeKeyName, type->ext );
3295|    }
3296|
3297|    /* HKEY_CLASSES_ROOT\.(ext)\標準 に (ext)file を設定する */
3298|    else {
3299|      strcpy( s, "." );  strcat( s, type->ext );
3300|
3301|      ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
3302|        REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
3303|      if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3304|
3305|      strcpy( s, type->ext );  strcat( s, "file" );
3306|      typeKeyName_len = sizeof(typeKeyName);
3307|      ret = RegQueryValueEx( key, NULL, NULL, NULL, typeKeyName, &typeKeyName_len );
3308|      if ( ret == ERROR_SUCCESS && typeKeyName[0] != '\0' ) {
3309|        if ( stricmp( s, typeKeyName ) != 0 ) {
3310|
3311|          WinX_copyRegNest( HKEY_CLASSES_ROOT, s, HKEY_CLASSES_ROOT, typeKeyName );
3312|
3313|          /* バックアップを取る */
3314|          data.type = REG_SZ;  strcpy( data.data, typeKeyName );
3315|          data.size = strlen( typeKeyName );
3316|          sprintf( typeKeyName, ".%s\\backup", type->ext );
3317|          WinX_setReg( HKEY_CLASSES_ROOT, typeKeyName, false, &data );
3318|
3319|          /* リンク先を変える */
3320|          data.type = REG_SZ;
3321|          sprintf( data.data, "%sfile", type->ext );
3322|          data.size = strlen( typeKeyName );
3323|          sprintf( typeKeyName, ".%s", type->ext );
3324|          WinX_setReg( HKEY_CLASSES_ROOT, typeKeyName, true, &data );
3325|        }
3326|      }
3327|      else {
3328|        ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)s, strlen( s ) );
3329|
3330|        /* アンインストール時に消すようにする */
3331|        data.type = REG_SZ;  strcpy( data.data, "" );
3332|        data.size = strlen( typeKeyName );
3333|        sprintf( typeKeyName, ".%s\\backup", type->ext );
3334|        WinX_setReg( HKEY_CLASSES_ROOT, typeKeyName, false, &data );
3335|      }
3336|      strcpy( typeKeyName, s );
3337|
3338|      ret = RegCloseKey( key );
3339|      if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
3340|    }
3341|
3342|    /* HKEY_CLASSES_ROOT\(ext)file を開く */
3343|    ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, typeKeyName, 0, 0,
3344|      REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
3345|
3346|    /* HKEY_CLASSES_ROOT\(ext)file\標準 に タイプの説明 を設定する */
3347|    if ( type->explain != NULL ) {
3348|      ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)type->explain, strlen(type->explain) );
3349|      if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3350|    }
3351|
3352|    /* HKEY_CLASSES_ROOT\(ext)file\EditFlags にダウンロードの設定をする */
3353|    {
3354|      static  char  flags11[4] = { 0x00, 0x00, 0x00, 0x00 }; /* ダウンロード時に確認する */
3355|      static  char  flags10[4] = { 0x00, 0x00, 0x01, 0x00 }; /* ダウンロード時に確認しない */
3356|
3357|      if ( type->bDownChk )
3358|        ret = RegSetValueEx( key, "EditFlags", 0, REG_BINARY, (WinX_DataPtr)flags11, sizeof(flags11) );
3359|      else
3360|        ret = RegSetValueEx( key, "EditFlags", 0, REG_BINARY, (WinX_DataPtr)flags10, sizeof(flags10) );
3361|      if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3362|    }
3363|
3364|    /* HKEY_CLASSES_ROOT\(ext)file を閉じる */
3365|    ret = RegCloseKey( key );
3366|    if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
3367|
3368|    /* HKEY_CLASSES_ROOT\(ext)file\CLSID を CLSID_BK に変えて、レジストリの設定を有効にする */
3369|    {
3370|      char  from[512];
3371|      char  to[512];
3372|
3373|      sprintf( from, "%s\\CLSID", typeKeyName );
3374|      if ( WinX_isExistReg( HKEY_CLASSES_ROOT, from, true, false ) ) {
3375|        sprintf( to, "%s\\CLSID_BK", typeKeyName );
3376|        WinX_copyRegNest( HKEY_CLASSES_ROOT, to, HKEY_CLASSES_ROOT, from );
3377|        WinX_delRegNest( HKEY_CLASSES_ROOT, from );
3378|      }
3379|    }
3380|
3381|    /* HKEY_CLASSES_ROOT\(ext)file\DefaultIcon にアイコンのパスと番号を設定する */
3382|    if ( type->iIcon != -1 ) {
3383|
3384|      {
3385|        char  from[512];
3386|        char  to[512];
3387|
3388|        sprintf( from, "%s\\DefaultIcon", typeKeyName );
3389|        sprintf( to, "%s\\DefaultIcon_BK", typeKeyName );
3390|        if ( WinX_isExistReg( HKEY_CLASSES_ROOT, from, true, false ) &&
3391|             ! WinX_isExistReg( HKEY_CLASSES_ROOT, to, true, false ) ) {
3392|          WinX_copyRegNest( HKEY_CLASSES_ROOT, to, HKEY_CLASSES_ROOT, from );
3393|          WinX_delRegNest( HKEY_CLASSES_ROOT, from );
3394|        }
3395|      }
3396|
3397|      sprintf( s, "%s\\DefaultIcon", typeKeyName );
3398|      ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, NULL, REG_OPTION_NON_VOLATILE,
3399|        KEY_ALL_ACCESS, NULL, &key, NULL );
3400|
3401|      if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3402|
3403|      if ( type->iconPath == NULL || strcmp( type->iconPath, "" ) == 0 )
3404|        strcpy( s, exePath );
3405|      else
3406|        StrX_cpyAbsPath2( s, type->iconPath, sizeof(s), exePath );
3407|      sprintf( strchr( s, '\0' ), ",%d", type->iIcon );
3408|      ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)s, strlen(s) );
3409|      if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3410|
3411|      ret = RegCloseKey( key );
3412|      if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
3413|    }
3414|
3415|    for ( cmd = type->cmds; strcmp( cmd->name, "NULL" ) != 0; cmd++ ) {
3416|
3417|      /* デフォルト・コマンドなら HKEY_CLASSES_ROOT\(ext)file\shell\標準 にコマンド名を設定する */
3418|      sprintf( s, "%s\\shell", typeKeyName );
3419|      ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
3420|        REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
3421|      if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3422|
3423|      len = sizeof(s);
3424|      ret = RegQueryValueEx( key, NULL, NULL, &typeTmp, s, &len );
3425|      if ( ( cmd->defType == WinX_SubDef && ( ret == 2 || s[0] == '\0' ) ) ||
3426|             cmd->defType == WinX_Def ) {
3427|
3428|        ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)cmd->name, strlen(cmd->name) );
3429|        if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3430|      }
3431|      else {
3432|        ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)"", 0 );
3433|        if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3434|      }
3435|      ret = RegCloseKey( key );
3436|      if ( ret != ERROR_SUCCESS ) { Errors_printf_release( "%s", typeKeyName );  WinX_error(); } /* WinX_throw( ret ); */
3437|
3438|      /* HKEY_CLASSES_ROOT\(ext)file\shell\(cmd_name)\標準 にメニュー表示内容を設定する */
3439|      /* HKEY_CLASSES_ROOT\(ext)file\shell\(cmd_name)\EditFlags に設定する */
3440|      {
3441|        static  char  flags2[4] = { 0x01, 0x00, 0x00, 0x00 };
3442|        DWORD  flags;
3443|        DWORD  size;
3444|        DWORD  type;
3445|
3446|        sprintf( s, "%s\\shell\\%s", typeKeyName, cmd->name );
3447|        ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
3448|          REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
3449|        if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3450|
3451|        ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)cmd->caption, strlen(cmd->caption) );
3452|        if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3453|
3454|        ret = RegSetValueEx( key, "EditFlags", 0, REG_BINARY, (WinX_DataPtr)flags2, sizeof(flags2) );
3455|        if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3456|
3457|        /* HKEY_CLASSES_ROOT\(ext)file\Shell\(cmd)\BrowserFlags と 〜\ExplorerFlags を改名する */
3458|        /* HKEY_CLASSES_ROOT\(ext)file\Shell\(cmd) にある DWORD 型 */
3459|        /* データ BrowserFlags(フォルダ), ExplorerFlags(エクスプローラ) の */
3460|        /* フラグ値 0x10 が立っていると、.zip 形式のときは、エクスプローラが展開します。 */
3461|        /* フラグ値 0x02 が立っていると、新規ウィンドウを開きます。 */
3462|        /* これらは、本関数で登録したインストール情報より優先されるため、データ名を */
3463|        /* BrowserFlaga_backup のように変えています。*/
3464|        ret = RegQueryValueEx( key, "BrowserFlags", 0, &type, (char*)&flags, &size );
3465|        if ( ret == ERROR_SUCCESS ) {
3466|          if ( type != REG_DWORD )  error();
3467|          ret = RegSetValueEx( key, "BrowserFlags_backup", 0, REG_DWORD, (char*)&flags, sizeof(flags) );
3468|          WinX_delReg( key, "BrowserFlags", false );
3469|        }
3470|
3471|        ret = RegQueryValueEx( key, "ExplorerFlags", 0, &type, (char*)&flags, &size );
3472|        if ( ret == ERROR_SUCCESS ) {
3473|          if ( type != REG_DWORD )  error();
3474|          ret = RegSetValueEx( key, "ExplorerFlags_backup", 0, REG_DWORD, (char*)&flags, sizeof(flags) );
3475|          WinX_delReg( key, "ExplorerFlags", false );
3476|        }
3477|
3478|        ret = RegCloseKey( key );
3479|        if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
3480|      }
3481|
3482|      /* HKEY_CLASSES_ROOT\(ext)file\shell\(cmd_name)\ddeexec を改名する */
3483|      /* HKEY_CLASSES_ROOT\(ext)file\Shell\(cmd)\BrowserFlags と同じ理由による */
3484|      sprintf( s, "%s\\shell\\%s\\ddeexec", typeKeyName, cmd->name );
3485|      sprintf( x, "%s\\shell\\%s\\ddeexec_backup", typeKeyName, cmd->name );
3486|      if ( WinX_isExistReg( HKEY_CLASSES_ROOT, s, true, true ) ) {
3487|        WinX_copyRegNest( HKEY_CLASSES_ROOT, x, HKEY_CLASSES_ROOT, s );
3488|        WinX_delRegNest( HKEY_CLASSES_ROOT, s );
3489|      }
3490|
3491|      /* HKEY_CLASSES_ROOT\(ext)file\shell\(cmd_name)\command\標準 にコマンドを設定する */
3492|      {
3493|        char  cmdLine[512];
3494|
3495|        sprintf( s, "%s\\shell\\%s\\command", typeKeyName, cmd->name );
3496|        ret = RegCreateKeyEx( HKEY_CLASSES_ROOT, s, 0, 0,
3497|          REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisp );
3498|        if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3499|
3500|        if ( cmd->exePath == NULL ||  cmd->exePath[0] == '\0' )
3501|          sprintf( cmdLine, "\"%s\" %s", exePath, cmd->command );
3502|        else {
3503|          StrX_cpyAbsPath2( s, cmd->exePath, sizeof(s), exePath );
3504|          sprintf( cmdLine, "\"%s\" %s", s, cmd->command );
3505|        }
3506|        ret = RegSetValueEx( key, NULL, 0, REG_SZ, (WinX_DataPtr)cmdLine, strlen(cmdLine) );
3507|        if ( ret != ERROR_SUCCESS )   WinX_throw( ret );
3508|
3509|        RegCloseKey( key );
3510|        if ( ret != ERROR_SUCCESS )  WinX_throw( ret );
3511|      }
3512|    }
3513|  }
3514|  ERRORS_FUNC_END( WinX_Inst_install );
3515|}
3516|#endif
3517|
3518| 
3519|/**************************************************************************
3520|  11-2. <<< [WinX_Inst_uninstall] レジストリ情報をアンインストールする >>> 
3521|【引数】
3522|  ・WinX_Inst*  m;  インストール時に使ったインストール情報
3523|  ・char*  exePath;    メインとなる実行ファイルの絶対パス
3524|  ・bool*  enables;    拡張子別アンインストール許可・不許可(NULL=全部許可)
3525|【補足】
3526|・(未対応)アンインストールするときは、実行ファイル名をチェックして、
3527|  合っていなかったら、open2, open3, ... を調べる。
3528|***************************************************************************/
3529|#ifdef  USES_BIGSTACK
3530|void  WinX_Inst_uninstall( WinX_Inst* m, const char* exePath, bool* enables )
3531|{
3532|  WinX_InstType*  type;
3533|  WinX_InstCmd*   cmd;
3534|  char  s[256];
3535|  char  typeKeyName[256];
3536|
3537|  ERRORS_FUNC_START( WinX_Inst_uninstall );
3538|
3539|  /* WinX_InstType の設定をレジストリに設定する */
3540|  for ( type = m->types; strcmp( type->ext, "NULL" ) != 0; type++ ) {
3541|
3542|    if ( enables != NULL && enables[ type - m->types ] )
3543|      continue;
3544|
3545|    if ( strcmp( type->ext, "*" ) == 0 || stricmp( type->ext, "folder" ) == 0 ) {
3546|      strcpy( typeKeyName, type->ext );
3547|    }
3548|    else {
3549|      /* HKEY_CLASSES_ROOT\.(ext)\標準 を typeKeyName に取得する */
3550|      c_try {
3551|        strcpy( s, "." );  strcat( s, type->ext );
3552|        WinX_getReg_s( HKEY_CLASSES_ROOT, s, NULL, typeKeyName, sizeof(typeKeyName) );
3553|      }
3554|      c_catch ( Errors_Msg*, msg ) {
3555|        if ( msg->code != WinX_Err_NoRegKey )  c_throw_again();
3556|        typeKeyName[0] = '\0';
3557|      } c_end_catch;
3558|      if ( typeKeyName[0] == '\0' )  continue;
3559|
3560|      /* typeKeyName が標準名でなかったら、本モジュールがインストールしていないものとして何もしない */
3561|      sprintf( s, "%sfile", type->ext );
3562|      if ( strcmp( s, typeKeyName ) != 0 )  continue;
3563|    }
3564|
3565|    /* HKEY_CLASSES_ROOT\(ext)file\DefaultIcon を削除する */
3566|    /* sprintf( s, "%s\\DefaultIcon", typeKeyName ); */
3567|    /* WinX_delRegNest( HKEY_CLASSES_ROOT, s ); */ /* アンインストールを先にすると元々あったのさえ削除してしまう */
3568|    {
3569|      char  from[512];
3570|      char  to[512];
3571|
3572|      sprintf( from, "%s\\DefaultIcon_BK", typeKeyName );
3573|      if ( WinX_isExistReg( HKEY_CLASSES_ROOT, from, true, false ) ) {
3574|        sprintf( to, "%s\\DefaultIcon", typeKeyName );
3575|        WinX_delRegNest( HKEY_CLASSES_ROOT, to );
3576|        WinX_copyRegNest( HKEY_CLASSES_ROOT, to, HKEY_CLASSES_ROOT, from );
3577|        WinX_delRegNest( HKEY_CLASSES_ROOT, from );
3578|      }
3579|    }
3580|
3581|    /* HKEY_CLASSES_ROOT\(ext)file\CLSID_BK CLSID に戻す */
3582|    {
3583|      char  from[512];
3584|      char  to[512];
3585|
3586|      sprintf( from, "%s\\CLSID_BK", typeKeyName );
3587|      if ( WinX_isExistReg( HKEY_CLASSES_ROOT, from, true, false ) ) {
3588|        sprintf( to, "%s\\CLSID", typeKeyName );
3589|        WinX_copyRegNest( HKEY_CLASSES_ROOT, to, HKEY_CLASSES_ROOT, from );
3590|        WinX_delRegNest( HKEY_CLASSES_ROOT, from );
3591|      }
3592|    }
3593|
3594|    /* HKEY_CLASSES_ROOT\(ext)file\shell\(cmd) を削除する */
3595|    for ( cmd = type->cmds; strcmp( cmd->name, "NULL" ) != 0; cmd++ ) {
3596|      sprintf( s, "%s\\shell\\%s", typeKeyName, cmd->name );
3597|      WinX_delRegNest( HKEY_CLASSES_ROOT, s );
3598|    }
3599|
3600|    /* HKEY_CLASSES_ROOT\(ext)file\(shell\) にサブキーが無ければ削除する */
3601|    sprintf( s, "%s\\shell", typeKeyName );
3602|    WinX_delRegIfNoSub( HKEY_CLASSES_ROOT, s );
3603|    sprintf( s, "%s", typeKeyName );
3604|    WinX_delRegIfNoSub( HKEY_CLASSES_ROOT, s );
3605|
3606|    /* HKEY_CLASSES_ROOT\.(ext)\backup を元に、 */
3607|    /* HKEY_CLASSES_ROOT\.(ext)\標準 を元に戻す */
3608|    /* backup が無ければ、HKEY_CLASSES_ROOT\.(ext) を削除する */
3609|    if ( strcmp( type->ext, "*" ) != 0 && stricmp( type->ext, "folder" ) != 0 ) {
3610|      bool  bResume = false;
3611|
3612|      c_try {
3613|        WinX_RegData  data;
3614|
3615|        WinX_RegData_init( &data, typeKeyName, sizeof(typeKeyName) );
3616|        sprintf( s, ".%s\\backup", type->ext );
3617|        WinX_getReg( HKEY_CLASSES_ROOT, s, false, &data );
3618|        WinX_delReg( HKEY_CLASSES_ROOT, s, false );
3619|        sprintf( s, ".%s", type->ext );
3620|        if ( data.size == 1 )
3621|          WinX_delRegNest( HKEY_CLASSES_ROOT, s );
3622|        else
3623|          WinX_setReg( HKEY_CLASSES_ROOT, s, true, &data );
3624|      } Errors_ignore_catch( case WinX_Err_NoRegData: );
3625|    }
3626|  }
3627|  ERRORS_FUNC_END( WinX_Inst_uninstall );
3628|}
3629|#endif
3630|
3631| 
3632|/*------------------------------------------------------------------------*/
3633|/*  12. <<<< ◆(WinX_Autorun) CD-ROM 自動実行の情報 >>>> */ 
3634|/*------------------------------------------------------------------------*/
3635|
3636|
3637| 
3638|/***********************************************************************
3639|  12-1. <<< [WinX_Autorun_read] Autorun.inf を読み込む >>> 
3640|【引数】
3641|  ・WinX_Autorun*  m;   Autorun.inf の情報の格納先
3642|  ・char*  path;           Autorun.inf のパス
3643|************************************************************************/
3644|#ifdef  USES_INIFILE
3645|void  WinX_Autorun_read( WinX_Autorun* m, const char* path )
3646|{
3647|  IniFile_Read  f;
3648|  int   i;
3649|  char  f_buf[256];
3650|  char  name[256];
3651|  char*  p;
3652|
3653|  ERRORS_FUNC_START( WinX_Autorun_read );
3654|
3655|  strcpy( m->autorun_path, path );
3656|  IniFile_Read_init( &f, path, f_buf, sizeof(f_buf) );
3657|  IniFile_Read_setSection( &f, "Autorun" );
3658|  IniFile_Read_getPlusVar( &f, "open", "s", m->open, "" );
3659|  IniFile_Read_getPlusVar( &f, "icon", "s", m->iconPath, "" );
3660|
3661|  /* iconNum */
3662|  p =  StrX_RSearchC2( m->iconPath, ',' );
3663|  if ( p != NULL ) {
3664|    m->iconNum = atoi( p + 1 );
3665|    *p = '\0';
3666|  }
3667|  else
3668|    m->iconNum = 0;
3669|
3670|  /* captions, commands */
3671|  i = 0;
3672|  while ( IniFile_Read_getNextVar( &f, name, "s", m->captions[i] ) != -1L ) {
3673|    if ( strnicmp( name, "shell", 5 ) != 0 )  break;
3674|    p =  StrX_RSearchC2( m->iconPath, '\\' );
3675|    if ( p != NULL && p > name + 5 && stricmp( p + 1, "command" ) == 0 ) {
3676|      strcpy( m->commands[i], m->captions[i] );
3677|      IniFile_Read_getNextVar( &f, name, "s", m->captions[i] );
3678|    }
3679|    else {
3680|      IniFile_Read_getNextVar( &f, name, "s", m->commands[i] );
3681|    }
3682|    if ( strnicmp( name, "shell", 5 ) != 0 )  break;
3683|    i++;
3684|  }
3685|  m->nCommand = i;
3686|
3687|  IniFile_Read_finish( &f );
3688|
3689|  ERRORS_FUNC_END( WinX_Autorun_read );
3690|}
3691|#endif
3692| 
3693|/***********************************************************************
3694|  12-2. <<< [WinX_Autorun_exec] Autorun.inf の情報からコマンドを実行する >>> 
3695|【引数】
3696|  ・WinX_Autorun*  m;   Autorun.inf の情報
3697|  ・char*  iCommand;       実行するコマンドの番号(0〜=shell、-1=open)
3698|************************************************************************/
3699|#ifdef  USES_FILEX
3700|void  WinX_Autorun_exec( WinX_Autorun* m, int iCommand )
3701|{
3702|  char   cmd2[_MAX_PATH];
3703|  char   curDir[_MAX_PATH];
3704|  char*  p;
3705|
3706|  ERRORS_FUNC_START( WinX_Autorun_exec );
3707|
3708|  p = WinX_Autorun_getCmdPath( m, iCommand, cmd2, sizeof(cmd2) );
3709|  StrX_cpyFolder( curDir, cmd2 );
3710|
3711|  ShellExecute( NULL, NULL, cmd2, p, curDir, SW_SHOWNORMAL );
3712|
3713|  ERRORS_FUNC_END( WinX_Autorun_exec );
3714|}
3715|#endif
3716| 
3717|/***********************************************************************
3718|  12-3. <<< [WinX_Autorun_getCmdPath] コマンドの実行ファイル部とパラメータ部を分ける >>> 
3719|【引数】
3720|  ・WinX_Autorun*  m;   Autorun.inf の情報
3721|  ・char*  iCommand;       実行するコマンドの番号(0〜=shell、-1=open)
3722|  ・char*  exe_path;       実行ファイルを格納する領域
3723|  ・int  exe_path_size;    exe_path のメモリサイズ
3724|  ・char*  返り値;         パラメータ部の先頭(exe_path 内)
3725|【補足】
3726|・exe_path には、'\0' で区切られた、実行ファイルとパラメータの両方が格納されます。
3727|************************************************************************/
3728|#ifdef  USES_FILEX
3729|char*  WinX_Autorun_getCmdPath( WinX_Autorun* m, int iCommand,
3730|  char* exe_path, int exe_path_size )
3731|{
3732|  char*  cmd;
3733|  char*  exeParameters;
3734|  char*  p;
3735|
3736|  ERRORS_FUNC_START( WinX_Autorun_getCmdPath );
3737|
3738|  if ( iCommand == -1 )  cmd = m->open;
3739|  else  cmd = m->commands[iCommand];
3740|
3741|  StrX_cpyAbsPath2( exe_path, cmd, exe_path_size, m->autorun_path );
3742|
3743|  p = strchr( exe_path, ' ' );
3744|  if ( p != NULL )  {
3745|    *p = '\0';  exeParameters = p + 1;
3746|    if ( ! FileX_isExist( exe_path ) ) {
3747|      *p = ' ';  exeParameters = NULL;
3748|    }
3749|  }
3750|  else  exeParameters = NULL;
3751|
3752|  ERRORS_FUNC_END( WinX_Autorun_getCmdPath );
3753|  return  exeParameters;
3754|}
3755|#endif
3756| 
3757|/*------------------------------------------------------------------------*/
3758|/*  13. <<<< ◆Windows 用高速ビットマップ描画(DDB = デバイス依存ビットマップ) >>>> */ 
3759|/*------------------------------------------------------------------------*/
3760|
3761| 
3762|/***********************************************************************
3763|  13-1. <<< [WinX_DDBmp_init] 初期化をする >>> 
3764|【引数】
3765|  ・char*  path;   DDB の保存先
3766|************************************************************************/
3767|void  WinX_DDBmp_init( WinX_DDBmp* m, const char* path )
3768|{
3769|  strcpy( m->path, path );
3770|  m->width = -1;
3771|  m->height = -1;
3772|  m->size = 0;
3773|  m->bmp = NULL;
3774|}
3775|
3776| 
3777|/***********************************************************************
3778|  13-2. <<< [WinX_DDBmp_finish] 後始末をする >>> 
3779|************************************************************************/
3780|void  WinX_DDBmp_finish( WinX_DDBmp* m )
3781|{
3782|  ASSERT( m->bmp == NULL );
3783|
3784|  if ( m->size != 0 )
3785|    remove( m->path );
3786|}
3787|
3788|
3789| 
3790|/***********************************************************************
3791|  13-3. <<< [WinX_DDBmp_openForWrite] DDBの作成を開始する >>> 
3792|【引数】
3793|  ・HDC  windowDC;    ウィンドウから取得したデバイスコンテキスト
3794|  ・int  width;    ビットマップの幅(0以上)
3795|  ・int  heifht;   ビットマップの高さ(0以上)
3796|  ・HDC  返り値;      DDB に対して描画できるデバイスコンテキスト
3797|【補足】
3798|・プログラミング例
3799|  CDC*   bmpDC;
3800|  bmpDC = CDC::FromHandle( WinX_DDBmp_openForWrite( &ddb, hDC, width, height ) );
3801|  bmpDC->Rectangle(0,0,100,100);
3802|  bmpDC->Detach();
3803|  WinX_DDBmp_closeForWrite( &ddb );
3804|************************************************************************/
3805|HDC  WinX_DDBmp_openForWrite( WinX_DDBmp* m, HDC windowDC, int width, int height )
3806|{
3807|  ASSERT( m->bmp == NULL );
3808|  ASSERT( width >= 0 );
3809|  ASSERT( height >= 0 );
3810|
3811|  m->width = width;
3812|  m->height = height;
3813|  m->bmp = CreateCompatibleBitmap( windowDC, m->width, m->height );
3814|  m->bmpDC = CreateCompatibleDC( windowDC );
3815|  m->oldBmp = SelectObject( m->bmpDC, m->bmp );
3816|
3817|  return  m->bmpDC;
3818|}
3819|
3820| 
3821|/***********************************************************************
3822|  13-4. <<< [WinX_DDBmp_closeForWrite] DDBの作成を終了して保存する >>> 
3823|【補足】
3824|・WinX_DDBmp_openForWrite で取得した DC が CDC クラスなどにリンクしていたときは、
3825|  この関数を呼び出す前にリンクを解除してください。
3826|  CDC*   bmpDC;
3827|  bmpDC = CDC::FromHandle( WinX_DDBmp_openForWrite( &ddb, hDC ) );
3828|  bmpDC->Rectangle(0,0,100,100);
3829|  bmpDC->Detach();
3830|  WinX_DDBmp_closeForWrite( &ddb );
3831|************************************************************************/
3832|void  WinX_DDBmp_closeForWrite( WinX_DDBmp* m )
3833|{
3834|  HANDLE  f;
3835|  void*   bmpX;
3836|  HANDLE  fmap;
3837|  BITMAP  info;
3838|  BITMAPINFO  info2;
3839|
3840|  ASSERT( m->bmp != NULL );
3841|
3842|  GetObject( m->bmp, sizeof(info), &info );  // info.bmBits = NULL
3843|  info2.bmiHeader.biSize = sizeof(BITMAPINFO);
3844|  info2.bmiHeader.biWidth = info.bmWidth;
3845|  info2.bmiHeader.biHeight = info.bmHeight;
3846|  info2.bmiHeader.biPlanes = info.bmPlanes;
3847|  info2.bmiHeader.biBitCount = info.bmBitsPixel;
3848|  info2.bmiHeader.biCompression = BI_RGB;
3849|  info2.bmiHeader.biSizeImage = 0;
3850|  info2.bmiHeader.biXPelsPerMeter = 1;
3851|  info2.bmiHeader.biYPelsPerMeter = 1;
3852|  info2.bmiHeader.biClrUsed = 0;
3853|  info2.bmiHeader.biClrImportant = 0;
3854|
3855|  m->size = info.bmWidthBytes * info.bmHeight;
3856|  f = CreateFile( m->path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
3857|  fmap = CreateFileMapping( f, NULL, PAGE_READWRITE, 0, m->size, NULL );
3858|  bmpX = MapViewOfFile( fmap, FILE_MAP_WRITE, 0, 0, 0 );
3859|
3860|  GetDIBits( m->bmpDC, m->bmp, 0, info2.bmiHeader.biHeight, bmpX, &info2, DIB_RGB_COLORS );
3861|
3862|  UnmapViewOfFile( bmpX );
3863|  CloseHandle( fmap );
3864|  CloseHandle( f );
3865|
3866|  SelectObject( m->bmpDC, m->oldBmp );
3867|  DeleteObject( m->bmp );
3868|  DeleteDC( m->bmpDC );
3869|
3870|  m->bmp = NULL;
3871|}
3872|
3873|
3874| 
3875|/***********************************************************************
3876|  13-5. <<< [WinX_DDBmp_openForRead] 作成したDDBを開く >>> 
3877|【引数】
3878|  ・HDC  windowDC;    ウィンドウから取得したデバイスコンテキスト
3879|  ・HDC  返り値;      DDB に対して描画できるデバイスコンテキスト
3880|【補足】
3881|・プログラミング例。
3882|  bmpDC = WinX_DDBmp_openForRead( &ddb, hDC );
3883|  BitBlt( hDC, 0,0, ddb.width, ddb.height, bmpDC, 0, 0, SRCCOPY );
3884|  WinX_DDBmp_closeForRead( &ddb );
3885|************************************************************************/
3886|HDC  WinX_DDBmp_openForRead( WinX_DDBmp* m, HDC windowDC )
3887|{
3888|  HANDLE  f;
3889|  HANDLE  fmap;
3890|  void*   bmpX;
3891|  BITMAP  info;
3892|  BITMAPINFO  info2;
3893|  int  r;
3894|
3895|  ASSERT( m->size != 0 );
3896|
3897|
3898|  /* 背景ビットマップを動的に生成する。 */
3899|  m->bmp = CreateCompatibleBitmap( windowDC, m->width, m->height );
3900|  m->bmpDC = CreateCompatibleDC( windowDC );
3901|  m->oldBmp = SelectObject( m->bmpDC, m->bmp );
3902|
3903|  /* リードする */
3904|  f = CreateFile( m->path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
3905|  fmap = CreateFileMapping( f, NULL, PAGE_READONLY, 0, m->size, NULL );
3906|  bmpX = MapViewOfFile( fmap, FILE_MAP_READ, 0, 0, 0 );
3907|
3908|  GetObject( m->bmp, sizeof(info), &info );  // info.bmBits = NULL
3909|  info2.bmiHeader.biSize = sizeof(BITMAPINFO);
3910|  info2.bmiHeader.biWidth = info.bmWidth;
3911|  info2.bmiHeader.biHeight = info.bmHeight;
3912|  info2.bmiHeader.biPlanes = info.bmPlanes;
3913|  info2.bmiHeader.biBitCount = info.bmBitsPixel;
3914|  info2.bmiHeader.biCompression = BI_RGB;
3915|  info2.bmiHeader.biSizeImage = 0;
3916|  info2.bmiHeader.biXPelsPerMeter = 1;
3917|  info2.bmiHeader.biYPelsPerMeter = 1;
3918|  info2.bmiHeader.biClrUsed = 0;
3919|  info2.bmiHeader.biClrImportant = 0;
3920|
3921|  r = SetDIBits( m->bmpDC, m->bmp, 0, info2.bmiHeader.biHeight, bmpX, &info2, DIB_RGB_COLORS );
3922|
3923|  UnmapViewOfFile( bmpX );
3924|  CloseHandle( fmap );
3925|  CloseHandle( f );
3926|
3927|  return  m->bmpDC;
3928|}
3929|
3930| 
3931|/***********************************************************************
3932|  13-6. <<< [WinX_DDBmp_closeForRead] 作成したDDBを閉じる >>> 
3933|************************************************************************/
3934|void  WinX_DDBmp_closeForRead( WinX_DDBmp* m )
3935|{
3936|  SelectObject( m->bmpDC, m->oldBmp );
3937|  DeleteObject( m->bmp );
3938|  DeleteDC( m->bmpDC );
3939|
3940|  m->bmp = NULL;
3941|}
3942|
3943|
3944| 
3945|/***********************************************************************
3946|  13-7. <<< [WinX_DDBmp_readDirect] 作成したDDBを描画する >>> 
3947|【引数】
3948|  ・HDC  dc;     ウィンドウやサーフェスなどから取得したデバイスコンテキスト
3949|  ・int  x, y;   描画位置
3950|************************************************************************/
3951|bool  WinX_DDBmp_readDirect( WinX_DDBmp* m, HDC dc, int x, int y )
3952|{
3953|  HANDLE  f;
3954|  HANDLE  fmap;
3955|  void*   bmpX;
3956|  BITMAPINFO  info2;
3957|  int  r;
3958|
3959|  ASSERT( m->size != 0 );
3960|
3961|  /* リードする */
3962|  f = CreateFile( m->path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
3963|  fmap = CreateFileMapping( f, NULL, PAGE_READONLY, 0, m->size, NULL );
3964|  bmpX = MapViewOfFile( fmap, FILE_MAP_READ, 0, 0, 0 );
3965|
3966|  info2.bmiHeader.biSize = sizeof(BITMAPINFO);
3967|  info2.bmiHeader.biWidth = m->width;
3968|  info2.bmiHeader.biHeight = m->height;
3969|  info2.bmiHeader.biPlanes = GetDeviceCaps( dc, PLANES );
3970|  info2.bmiHeader.biBitCount = GetDeviceCaps( dc, BITSPIXEL );
3971|  info2.bmiHeader.biCompression = BI_RGB;
3972|  info2.bmiHeader.biSizeImage = 0;
3973|  info2.bmiHeader.biXPelsPerMeter = 1;
3974|  info2.bmiHeader.biYPelsPerMeter = 1;
3975|  info2.bmiHeader.biClrUsed = 0;
3976|  info2.bmiHeader.biClrImportant = 0;
3977|
3978|  r = SetDIBitsToDevice( dc, x, y, info2.bmiHeader.biWidth, info2.bmiHeader.biHeight,
3979|        0, 0, 0, info2.bmiHeader.biHeight, bmpX, &info2, DIB_RGB_COLORS );
3980|
3981|  UnmapViewOfFile( bmpX );
3982|  CloseHandle( fmap );
3983|  CloseHandle( f );
3984|
3985|  return  r != 0;
3986|}
3987| 
3988|/*------------------------------------------------------------------------*/
3989|/*  14. <<<< ◆DDE関係 >>>> */ 
3990|/*------------------------------------------------------------------------*/
3991|
3992|DWORD  WinX_dde = 0;
3993|char   WinX_dde_command[280];
3994|char   WinX_dde_service[80];
3995|char   WinX_dde_topic[80];
3996|
3997| 
3998|/**************************************************************************
3999|  14-1. <<< [WinX_callbackDDE] DDE コールバック >>> 
4000|【補足】
4001|・内部用です
4002|***************************************************************************/
4003|HDDEDATA CALLBACK  WinX_callbackDDE( UINT uType, UINT uFmt, HCONV hconv, HSZ hsz1,
4004| HSZ hsz2, HDDEDATA hdata, DWORD dwData1, DWORD dwData2 )
4005|{
4006|  ERRORS_FUNC_START( WinX_callbackDDE );
4007|
4008|//MessageBox( NULL, "A", NULL, MB_OK );
4009|  switch ( uType ) {
4010|    #if 0
4011|    case XTYP_REGISTER: {
4012|      char  name[256];
4013|      char  name2[256];
4014|
4015|      DdeQueryString( WinX_dde, hsz1, name, sizeof(name), CP_WINANSI );
4016|      DdeQueryString( WinX_dde, hsz2, name2, sizeof(name2), CP_WINANSI );
4017|
4018|      Errors_printf( "name = %s, name2 = %s", name, name2 );
4019|      ERRORS_FUNC_END( WinX_callbackDDE );
4020|      return (HDDEDATA)NULL;
4021|    }
4022|    #endif
4023|
4024|    case XTYP_ADVDATA:
4025|      ERRORS_FUNC_END( WinX_callbackDDE );
4026|      return (HDDEDATA)DDE_FACK;
4027|    default:
4028|      ERRORS_FUNC_END( WinX_callbackDDE );
4029|      return (HDDEDATA)NULL;
4030|  }
4031|}
4032|
4033| 
4034|/**************************************************************************
4035|  14-2. <<< [WinX_isOpenDDE] DDE サービスが活動中か調べる >>> 
4036|【引数】
4037|  ・char*  service;    サービス名(アプリケーション名)
4038|  ・char*  topic;      トピック名(プロパティ名)
4039|***************************************************************************/
4040|#if defined(USES_EXCEPT3)
4041|bool  WinX_isOpenDDE( const char* service, char* topic )
4042|{
4043|  bool  ret;
4044|  DWORD  dde = 0;
4045|  bool   bDde = false;    /* dde が有効かどうか */
4046|  HSZ  hService = NULL, hTopic = NULL;
4047|  HCONV  con;
4048|
4049|  ERRORS_FUNC_START( WinX_isOpenDDE );
4050|
4051|  c_try {
4052|
4053|    /* DDE 通信の初期化 */
4054|    ret = DdeInitialize( &dde, WinX_callbackDDE,
4055|      APPCMD_CLIENTONLY, 0L );
4056|    if ( ret != DMLERR_NO_ERROR )  WinX_throwDde( dde );
4057|    bDde = true;
4058|
4059|    /* 通信を開始する */
4060|    hService = DdeCreateStringHandle( dde, service, CP_WINANSI );
4061|    hTopic = DdeCreateStringHandle( dde, topic, CP_WINANSI );
4062|    if ( hService == NULL || hTopic == NULL )  WinX_throwDde( dde );
4063|    con = DdeConnect( dde, hService, hTopic, NULL );
4064|
4065|    /* サービスがあるかどうか判定する */
4066|    if ( con == NULL ) {
4067|      ret = false;
4068|    }
4069|    else {
4070|      DdeDisconnect( con );
4071|      ret = true;
4072|    }
4073|
4074|    /* 通信を終了する */
4075|    DdeFreeStringHandle( dde, hService );
4076|    DdeFreeStringHandle( dde, hTopic );
4077|
4078|    /* DDE 通信の後始末 */
4079|    DdeUninitialize( dde );
4080|  }
4081|  c_catch( Errors_Msg*, msg ) {
4082|    if ( hService != NULL )  DdeFreeStringHandle( dde, hService );
4083|    if ( hTopic != NULL )  DdeFreeStringHandle( dde, hTopic );
4084|    if ( bDde )  DdeUninitialize( dde );
4085|    c_throw_again();
4086|  } c_end_catch;
4087|
4088|  ERRORS_FUNC_END( WinX_isOpenDDE );
4089|  return  ret;
4090|}
4091|#endif
4092|
4093|
4094| 
4095|/**************************************************************************
4096|  14-3. <<< [WinX_sendDDE] DDE データを送る >>> 
4097|【引数】
4098|  ・char*  command;    起動コマンド
4099|  ・char*  service;    サービス名(アプリケーション名)
4100|  ・char*  topic;      トピック名(プロパティ名)
4101|  ・void*  data;       送るデータが格納されている領域の先頭アドレス
4102|  ・int    data_size;  送るデータのサイズ(文字列の場合、末尾の'\0'を含まない)
4103|  ・int    sendType;   WinX_Request or WinX_Execute
4104|【補足】
4105|・サービスを提供するアプリが無い場合、起動コマンドを実行してから
4106|  DDE データを送ります。
4107|・command には、実行ファイルの絶対パスとオプションを指定します。
4108|  ([スタート]-[プログラムを指定して実行]と同じ)
4109|・service と topic と「data のフォーマット」については、
4110|  ソース(サーバ・アプリケーション)の DDE の仕様を調べてください。
4111|・大量のデータを効率よく送る場合は、直接 API を呼び出してください。
4112|***************************************************************************/
4113|#if defined(USES_EXCEPT3)
4114|void  WinX_sendDDE( const char* command, const char* service,
4115|  const char* topic, const void* data, int data_size, int sendType )
4116|{
4117|  int  ret;
4118|  DWORD  dde = 0;
4119|  bool   bDde = false;    /* dde が有効かどうか */
4120|  HSZ  hService = NULL, hTopic = NULL;
4121|  HCONV  con;
4122|
4123|  ERRORS_FUNC_START( WinX_sendDDE );
4124|
4125|  c_try {
4126|
4127|    /* DDE 通信の初期化 */
4128|    ret = DdeInitialize( &dde, WinX_callbackDDE,
4129|      APPCLASS_STANDARD | APPCMD_CLIENTONLY /*| MF_POSTMSGS*/, 0L );
4130|    if ( ret != DMLERR_NO_ERROR )  WinX_throwDde( dde );
4131|    WinX_dde = dde;
4132|    bDde = true;
4133|
4134|    /* 通信を開始する */
4135|    hService = DdeCreateStringHandle( dde, service, CP_WINANSI );
4136|    hTopic = DdeCreateStringHandle( dde, topic, CP_WINANSI );
4137|    StrX_cpy( WinX_dde_command, command, sizeof(WinX_dde_command) );
4138|    StrX_cpy( WinX_dde_service, service, sizeof(WinX_dde_service) );
4139|    StrX_cpy( WinX_dde_topic, topic, sizeof(WinX_dde_topic) );
4140|    if ( hService == NULL || hTopic == NULL )  WinX_throwDde( dde );
4141|    con = DdeConnect( dde, hService, hTopic, NULL );  /* status=(fAck fBusy) */
4142|    // con = DdeReconnect( dde );  /* status=(fAck fBusy) */
4143|
4144|    /* もし、サービスが無かったら、サービスを起動する */
4145|    if ( con == NULL ) {
4146|      //WinExec( command, SW_SHOWNORMAL );
4147|      STARTUPINFO  sinfo;
4148|      PROCESS_INFORMATION  proc;
4149|
4150|      ZeroMemory( &sinfo, sizeof( sinfo ) );
4151|      ZeroMemory( &proc, sizeof( proc ) );
4152|      sinfo.cb = sizeof( sinfo );
4153|      sinfo.dwFlags = STARTF_USESHOWWINDOW;
4154|      sinfo.wShowWindow = SW_SHOWNORMAL;
4155|      if ( CreateProcess( NULL, (char*)command, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS,
4156|          NULL, NULL, &sinfo, &proc ) == 0 ) {
4157|        WinX_error();
4158|      }
4159|
4160|      WaitForInputIdle( proc.hProcess, INFINITE );
4161|      CloseHandle( proc.hProcess );
4162|      CloseHandle( proc.hThread );
4163|
4164|      con = DdeConnect( dde, hService, hTopic, NULL );
4165|      if ( con == NULL )  WinX_throwDde( dde );
4166|    }
4167|
4168|    /* データを転送する */
4169|    if ( sendType == WinX_Request ) {  /* Syncro Call */
4170|      HSZ  hItem;
4171|
4172|      if ( *( (char*)data + data_size ) == '\0' )
4173|        hItem = DdeCreateStringHandle( dde, data, CP_WINANSI );
4174|      else {
4175|        char  dataX[256];
4176|
4177|        ASSERT( data_size < sizeof(dataX) );
4178|        memcpy( dataX, data, data_size );
4179|        dataX[data_size] = '\0';
4180|        hItem = DdeCreateStringHandle( dde, data, CP_WINANSI );
4181|      }
4182|
4183|      DdeClientTransaction( NULL, 0, con, hItem, CF_TEXT,
4184|        XTYP_REQUEST, 1000, NULL );
4185|
4186|      DdeFreeStringHandle( dde, hItem );
4187|    }
4188|    else if ( sendType == WinX_Execute ) {  /* Unyncro Call : Server will be disconnected strongly */
4189|      DWORD  res;
4190|
4191|      #if 1
4192|        HDDEDATA  r;
4193|        UINT  err;
4194|
4195|        for (;;) {
4196|          r = DdeClientTransaction( (void*)data, data_size, con, 0, 0,
4197|              XTYP_EXECUTE, 10000, &res );
4198|          if ( res == 0 || r != 0 )  break;
4199|          err = DdeGetLastError( dde );
4200|          if ( err != DMLERR_NOTPROCESSED )  /* 0x4009 */
4201|            WinX_throwDde( dde );
4202|        }
4203|      #else
4204|        HDDEDATA  hData;
4205|
4206|        hData = DdeCreateDataHandle( dde, (void*)data, data_size, 0, 0L, CF_TEXT, HDATA_APPOWNED );
4207|        if ( DdeClientTransaction( (void*)hData, -1, con, 0, 0,
4208|            XTYP_EXECUTE, 10000, &res ) == 0 )
4209|          WinX_throwDde( dde );
4210|
4211|        DdeFreeDataHandle( hData );
4212|      #endif
4213|    }
4214|
4215|    /* 通信を終了する */
4216|    DdeDisconnect( con );
4217|    DdeFreeStringHandle( dde, hService );
4218|    DdeFreeStringHandle( dde, hTopic );
4219|
4220|    /* DDE 通信の後始末 */
4221|    DdeUninitialize( dde );
4222|    WinX_dde = 0;
4223|  }
4224|  c_catch( Errors_Msg*, msg ) {
4225|    if ( hService != NULL )  DdeFreeStringHandle( dde, hService );
4226|    if ( hTopic != NULL )  DdeFreeStringHandle( dde, hTopic );
4227|    if ( bDde )  DdeUninitialize( dde );
4228|    c_throw_again();
4229|  } c_end_catch;
4230|
4231|  ERRORS_FUNC_END( WinX_sendDDE );
4232|}
4233|#endif
4234| 
4235|/**************************************************************************
4236|  14-4. <<< [WinX_receiveDDE] DDE データを受け取る >>> 
4237|【引数】
4238|  ・char*  command;    起動コマンド
4239|  ・char*  service;    サービス名(アプリケーション名)
4240|  ・char*  topic;      トピック名(プロパティ名)
4241|  ・void*  data;       受け取るデータを格納する領域の先頭アドレス
4242|  ・int    data_size;  data の領域のメモリサイズ
4243|  ・int    返り値;     受信したデータのサイズ
4244|【補足】
4245|・サービスを提供するアプリが無い場合、起動コマンドを実行してから
4246|  DDE データを受け取ります。
4247|・command には、実行ファイルの絶対パスとオプションを指定します。
4248|  ([スタート]-[プログラムを指定して実行]と同じ)
4249|・service と topic と「data のフォーマット」については、
4250|  ソース(サーバ・アプリケーション)の DDE の仕様を調べてください。
4251|・大量のデータを受け取る場合は、直接 API を呼び出してください。
4252|***************************************************************************/
4253|#if defined(USES_EXCEPT3)
4254|int  WinX_receiveDDE( const char* command, const char* service,
4255|  const char* topic, void* data, int data_size )
4256|{
4257|  int  ret;
4258|  DWORD  size;
4259|  DWORD  dde = 0;
4260|  bool   bDde = false;    /* dde が有効かどうか */
4261|  HSZ  hService = NULL, hTopic = NULL, hItem = NULL;
4262|  HCONV  con;
4263|  HDDEDATA  hData;
4264|  char*  dataSrc;
4265|
4266|  ERRORS_FUNC_START( WinX_receiveDDE );
4267|
4268|  c_try {
4269|
4270|    /* DDE 通信の初期化 */
4271|    ret = DdeInitialize( &dde, WinX_callbackDDE,
4272|      APPCLASS_STANDARD | APPCMD_CLIENTONLY, 0L );
4273|    if ( ret != DMLERR_NO_ERROR )  WinX_throwDde( dde );
4274|    bDde = true;
4275|
4276|    /* 通信を開始する */
4277|    hService = DdeCreateStringHandle( dde, service, CP_WINANSI );
4278|    hTopic = DdeCreateStringHandle( dde, topic, CP_WINANSI );
4279|    hItem = DdeCreateStringHandle( dde, "-1", CP_WINANSI );
4280|    if ( hService == NULL || hTopic == NULL )  WinX_throwDde( dde );
4281|    con = DdeConnect( dde, hService, hTopic, NULL );
4282|
4283|    /* もし、サービスが無かったら、サービスを起動する */
4284|    if ( con == NULL ) {
4285|
4286|      WinExec( command, SW_SHOWNORMAL );
4287|      #if 0
4288|      PROCESS_INFORMATION  proc;
4289|      if ( CreateProcess( NULL, (char*)command, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS,
4290|          NULL, NULL, NULL, &proc ) != 0 )
4291|        WinX_error();
4292|      WaitForInputIdle( proc.hProcess, INFINITE );
4293|      #endif
4294|
4295|      con = DdeConnect( dde, hService, hTopic, NULL );
4296|      if ( con == NULL ) {
4297|/*
4298|        WS( command );
4299|        WD( dde );
4300|        WD( hService );
4301|        WS( service );
4302|        WD( hTopic );
4303|        WS( topic );
4304|        WinX_throwDde( dde );
4305|*/
4306|      }
4307|    }
4308|
4309|    /* データを受信する */
4310|    hData = DdeClientTransaction( NULL, 0, con, hItem, CF_TEXT,
4311|      XTYP_REQUEST, 1000, NULL );
4312|    if ( hData == NULL )  WinX_throwDde( dde );
4313|    dataSrc = DdeAccessData( hData, &size );
4314|    strcpy( data, dataSrc );
4315|    DdeUnaccessData( hData );
4316|
4317|    /* 通信を終了する */
4318|    DdeDisconnect( con );
4319|    DdeFreeStringHandle( dde, hService );
4320|    DdeFreeStringHandle( dde, hTopic );
4321|
4322|    /* DDE 通信の後始末 */
4323|    DdeUninitialize( dde );
4324|  }
4325|  c_catch( Errors_Msg*, msg ) {
4326|    if ( hService != NULL )  DdeFreeStringHandle( dde, hService );
4327|    if ( hTopic != NULL )  DdeFreeStringHandle( dde, hTopic );
4328|    if ( bDde )  DdeUninitialize( dde );
4329|    c_throw_again();
4330|  } c_end_catch;
4331|
4332|  ERRORS_FUNC_END( WinX_receiveDDE );
4333|  return  (int)size;
4334|}
4335|#endif
4336|
4337| 
4338|/*------------------------------------------------------------------------*/
4339|/*  15. <<<< ◆(WinX_DdeServ) DDEサーバ >>>> */ 
4340|/*------------------------------------------------------------------------*/
4341|
4342|HDDEDATA CALLBACK WinX_DdeServ_callback_imp( UINT uType, UINT uFmt, HCONV hconv,
4343|  HSZ topicName, HSZ itemName, HDDEDATA hdata, DWORD dwData1, DWORD dwData2 );
4344|
4345|WinX_DdeServ*  WinX_ddeServ = NULL;
4346| 
4347|/***********************************************************************
4348|  15-1. <<< [WinX_DdeServ_init] DDEサーバーを起動する >>> 
4349|************************************************************************/
4350|void  WinX_DdeServ_init( WinX_DdeServ* m, const char* serviceName,
4351|  const char* topicName, const char* itemName, WinX_DdeServ_onMsgF onMsg )
4352|{
4353|  UINT  r;
4354|  HDDEDATA  r2;
4355|
4356|  ASSERT( WinX_ddeServ == NULL );
4357|
4358|  r = DdeInitialize( &m->handle, WinX_DdeServ_callback_imp,
4359|        CBF_SKIP_REGISTRATIONS, 0 );
4360|  if ( r != DMLERR_NO_ERROR )  error();
4361|
4362|  m->serviceName = DdeCreateStringHandle( m->handle, serviceName, CP_WINANSI );
4363|  m->topicName =   DdeCreateStringHandle( m->handle, topicName, CP_WINANSI );
4364|  m->itemName =    DdeCreateStringHandle( m->handle, itemName, CP_WINANSI );
4365|  strcpy( m->advdata, "0" );
4366|  m->onMsg = onMsg;
4367|
4368|  r2 = DdeNameService( m->handle, m->serviceName, 0, DNS_REGISTER );
4369|  if ( r2 == 0 )
4370|    { WinX_DdeServ_finish( m );  error(); }
4371|
4372|  WinX_ddeServ = m;
4373|}
4374|
4375|
4376| 
4377|/***********************************************************************
4378|  15-2. <<< [WinX_DdeServ_finish] DDEサーバーを終了する >>> 
4379|************************************************************************/
4380|void  WinX_DdeServ_finish( WinX_DdeServ* m )
4381|{
4382|  DdeFreeStringHandle( m->handle, m->serviceName );
4383|  DdeFreeStringHandle( m->handle, m->topicName );
4384|  DdeFreeStringHandle( m->handle, m->itemName );
4385|
4386|  DdeUninitialize( m->handle );
4387|
4388|  WinX_ddeServ = NULL;
4389|}
4390|
4391|
4392| 
4393|/***********************************************************************
4394|  15-3. <<< [WinX_DdeServ_callback_imp] DDEサーバーの内部コールバック関数 >>> 
4395|【補足】
4396|・内部用です。
4397|************************************************************************/
4398|HDDEDATA CALLBACK WinX_DdeServ_callback_imp( UINT uType, UINT uFmt, HCONV hconv,
4399|  HSZ topicName, HSZ itemName, HDDEDATA hdata, DWORD dwData1, DWORD dwData2 )
4400|{
4401|  WinX_DdeServ*  m = WinX_ddeServ;
4402|  char*  data;
4403|
4404|  switch ( uType ) {
4405|
4406|    case XTYP_CONNECT:
4407|      if ( topicName != m->topicName)  return (HDDEDATA)FALSE;
4408|      else  return (HDDEDATA)TRUE;
4409|
4410|    case XTYP_DISCONNECT:
4411|      return (HDDEDATA)TRUE;
4412|
4413|    case XTYP_REQUEST:
4414|      if( topicName != m->topicName || itemName != m->itemName )  return  NULL;
4415|      return  DdeCreateDataHandle( m->handle, m->advdata, 2, 0, m->itemName, CF_TEXT, 0 );
4416|
4417|    case XTYP_POKE:
4418|      if( topicName != m->topicName || itemName != m->itemName ) {
4419|        DdeFreeDataHandle( hdata );
4420|        return  DDE_FNOTPROCESSED;
4421|      }
4422|      data = DdeAccessData( hdata, NULL );
4423|      m->onMsg( XTYP_POKE, data );
4424|      DdeUnaccessData( hdata );
4425|      DdeFreeDataHandle( hdata );
4426|      return  (HDDEDATA)DDE_FACK;
4427|
4428|    case XTYP_ADVSTART:
4429|      if( topicName != m->topicName || itemName != m->itemName )  return  (HDDEDATA)FALSE;
4430|
4431|      m->advdata[0] = '0';  /* 初期化 */
4432|      return  (HDDEDATA)TRUE;
4433|
4434|    case XTYP_ADVSTOP:
4435|      return (HDDEDATA)TRUE;
4436|
4437|    case XTYP_ADVREQ:  /* from DdePostAdvise */
4438|      if( topicName != m->topicName || itemName != m->itemName )  return  NULL;
4439|      return  DdeCreateDataHandle( m->handle, m->advdata, 2, 0, m->itemName, CF_TEXT, 0 );  /* make advdata */
4440|
4441|    case XTYP_EXECUTE:
4442|      if ( topicName != m->topicName ) {
4443|        DdeFreeDataHandle(hdata);
4444|        return  DDE_FNOTPROCESSED;
4445|      }
4446|      data = DdeAccessData( hdata, NULL );
4447|      m->onMsg( XTYP_EXECUTE, data );
4448|      DdeUnaccessData( hdata );
4449|      DdeFreeDataHandle( hdata );
4450|      return (HDDEDATA)DDE_FACK;
4451|
4452|    default:
4453|      return (HDDEDATA)NULL;
4454|  }
4455|  return (HDDEDATA)NULL;
4456|}
4457|
4458| 
4459|/*------------------------------------------------------------------------*/
4460|/*  16. <<<< ◆(WinX_DdeAct) ファイルタイプの DDE アクション >>>> */ 
4461|/*------------------------------------------------------------------------*/
4462| 
4463|/**************************************************************************
4464|*  16-1. <<< [WinX_DdeAct_init] レジストリから DDE アクションを取得する >>> 
4465|*【引数】
4466|*  ・WinX_DdeAct*  m;   ファイルタイプの DDE アクション
4467|*  ・char* type;           ファイルタイプ名(通常、拡張子)
4468|*【補足】
4469|*・ファイルタイプ名は、レジストリの HKEY_CLASSES_ROOT を参照してください。
4470|***************************************************************************/
4471|void  WinX_DdeAct_init( WinX_DdeAct* m, const char* type )
4472|{
4473|  static char  key[256];
4474|
4475|  sprintf( key, "%s\\shell\\open\\command", type );
4476|  WinX_getReg_s( HKEY_CLASSES_ROOT, key, NULL, m->command, _MAX_PATH );
4477|  sprintf( key, "%s\\shell\\open\\ddeexec", type );
4478|  WinX_getReg_s( HKEY_CLASSES_ROOT, key, NULL, m->data, WinX_DdeAct_size );
4479|  sprintf( key, "%s\\shell\\open\\ddeexec\\Application", type );
4480|  WinX_getReg_s( HKEY_CLASSES_ROOT, key, NULL, m->service, WinX_DdeAct_size );
4481|  sprintf( key, "%s\\shell\\open\\ddeexec\\Topic", type );
4482|  WinX_getReg_s( HKEY_CLASSES_ROOT, key, NULL, m->topic, WinX_DdeAct_size );
4483|}
4484|
4485|
4486| 
4487|/**************************************************************************
4488|*  16-2. <<< [WinX_DdeAct_isOpen] DDE サービスが活動中か調べる >>> 
4489|*【引数】
4490|*  ・WinX_DdeAct* m;  ファイルタイプの DDE アクション
4491|***************************************************************************/
4492|#if defined(USES_EXCEPT3)
4493|bool  WinX_DdeAct_isOpen( WinX_DdeAct* m )
4494|{
4495|  return  WinX_isOpenDDE( m->service, m->topic );
4496|}
4497|#endif
4498|
4499| 
4500|/**************************************************************************
4501|*  16-3. <<< [WinX_DdeAct_send] DDE データを送る >>> 
4502|*【引数】
4503|*  ・WinX_DdeAct* m;  ファイルタイプの DDE アクション
4504|*  ・char*  topic;      トピック名(プロパティ名)(NULL or "" 可)
4505|*  ・void*  data;       送るデータが格納されている領域の先頭アドレス
4506|*  ・int    data_size;  送るデータのサイズ(文字列の場合、末尾の'\0'を含まない)
4507|*【補足】
4508|*・WinX_sendDDE WinX_DdeAct 型版です。
4509|*・topic を NULL か "" にすると、m 中のトピック名を使用します。
4510|***************************************************************************/
4511|#if defined(USES_EXCEPT3)
4512|void  WinX_DdeAct_send( WinX_DdeAct* m,
4513|  const char* topic, void* data, int data_size )
4514|{
4515|  if ( topic == NULL || topic[0] == '\0' )
4516|    WinX_sendDDE( m->command, m->service, m->topic, data, data_size, WinX_Execute );
4517|  else
4518|    WinX_sendDDE( m->command, m->service, topic, data, data_size, WinX_Execute );
4519|}
4520|#endif
4521|
4522| 
4523|/**************************************************************************
4524|*  16-4. <<< [WinX_DdeAct_receive] DDE データを受け取る >>> 
4525|*【引数】
4526|*  ・WinX_DdeAct* m;  ファイルタイプの DDE アクション
4527|*  ・char*  topic;      トピック名(プロパティ名)(NULL or "" 可)
4528|*  ・void*  data;       受け取るデータを格納する領域の先頭アドレス
4529|*  ・int    data_size;  data の領域のメモリサイズ
4530|*【補足】
4531|*・WinX_receiveDDE WinX_DdeAct 型版です。
4532|*・topic を NULL か "" にすると、m 中のトピック名を使用します。
4533|***************************************************************************/
4534|#if defined(USES_EXCEPT3)
4535|void  WinX_DdeAct_receive( WinX_DdeAct* m,
4536|  const char* topic, void* data, int data_size )
4537|{
4538|  if ( topic == NULL || topic[0] == '\0' )
4539|    WinX_receiveDDE( m->command, m->service, m->topic, data, data_size );
4540|  else
4541|    WinX_receiveDDE( m->command, m->service, topic, data, data_size );
4542|}
4543|#endif
4544|
4545|
4546| 
4547|