source: trunk/third/glib2/glib/gwin32.c @ 21369

Revision 21369, 33.6 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21368, which included commits to RCS files with non-trunk default branches.
Line 
1/* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1998  Peter Mattis, Spencer Kimball and Josh MacDonald
3 * Copyright (C) 1998-1999  Tor Lillqvist
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20
21/*
22 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
23 * file for a list of people on the GLib Team.  See the ChangeLog
24 * files for a list of changes.  These files are distributed with
25 * GLib at ftp://ftp.gtk.org/pub/gtk/.
26 */
27
28/*
29 * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
30 */
31
32#include "config.h"
33
34#include "glibconfig.h"
35
36#include <stdlib.h>
37#include <stdio.h>
38#include <string.h>
39#include <errno.h>
40
41#define STRICT                  /* Strict typing, please */
42#include <windows.h>
43#undef STRICT
44#ifndef G_WITH_CYGWIN
45#include <direct.h>
46#endif
47#include <errno.h>
48#include <ctype.h>
49#ifdef _MSC_VER
50#  include <io.h>
51#endif /* _MSC_VER */
52
53#include "glib.h"
54
55#ifdef G_WITH_CYGWIN
56#include <sys/cygwin.h>
57#endif
58
59#ifndef G_WITH_CYGWIN
60
61gint
62g_win32_ftruncate (gint  fd,
63                   guint size)
64{
65  return _chsize (fd, size);
66}
67
68#endif
69
70/**
71 * g_win32_getlocale:
72 *
73 * The setlocale in the Microsoft C library uses locale names of the
74 * form "English_United States.1252" etc. We want the UNIXish standard
75 * form "en_US", "zh_TW" etc. This function gets the current thread
76 * locale from Windows - without any encoding info - and returns it as
77 * a string of the above form for use in forming file names etc. The
78 * returned string should be deallocated with g_free().
79 *
80 * Returns: newly-allocated locale name.
81 **/
82
83/* Borrowed from GNU gettext 0.13.1: */
84/* Mingw headers don't have latest language and sublanguage codes.  */
85#ifndef LANG_AFRIKAANS
86#define LANG_AFRIKAANS 0x36
87#endif
88#ifndef LANG_ALBANIAN
89#define LANG_ALBANIAN 0x1c
90#endif
91#ifndef LANG_AMHARIC
92#define LANG_AMHARIC 0x5e
93#endif
94#ifndef LANG_ARABIC
95#define LANG_ARABIC 0x01
96#endif
97#ifndef LANG_ARMENIAN
98#define LANG_ARMENIAN 0x2b
99#endif
100#ifndef LANG_ASSAMESE
101#define LANG_ASSAMESE 0x4d
102#endif
103#ifndef LANG_AZERI
104#define LANG_AZERI 0x2c
105#endif
106#ifndef LANG_BASQUE
107#define LANG_BASQUE 0x2d
108#endif
109#ifndef LANG_BELARUSIAN
110#define LANG_BELARUSIAN 0x23
111#endif
112#ifndef LANG_BENGALI
113#define LANG_BENGALI 0x45
114#endif
115#ifndef LANG_BURMESE
116#define LANG_BURMESE 0x55
117#endif
118#ifndef LANG_CAMBODIAN
119#define LANG_CAMBODIAN 0x53
120#endif
121#ifndef LANG_CATALAN
122#define LANG_CATALAN 0x03
123#endif
124#ifndef LANG_CHEROKEE
125#define LANG_CHEROKEE 0x5c
126#endif
127#ifndef LANG_DIVEHI
128#define LANG_DIVEHI 0x65
129#endif
130#ifndef LANG_EDO
131#define LANG_EDO 0x66
132#endif
133#ifndef LANG_ESTONIAN
134#define LANG_ESTONIAN 0x25
135#endif
136#ifndef LANG_FAEROESE
137#define LANG_FAEROESE 0x38
138#endif
139#ifndef LANG_FARSI
140#define LANG_FARSI 0x29
141#endif
142#ifndef LANG_FRISIAN
143#define LANG_FRISIAN 0x62
144#endif
145#ifndef LANG_FULFULDE
146#define LANG_FULFULDE 0x67
147#endif
148#ifndef LANG_GAELIC
149#define LANG_GAELIC 0x3c
150#endif
151#ifndef LANG_GALICIAN
152#define LANG_GALICIAN 0x56
153#endif
154#ifndef LANG_GEORGIAN
155#define LANG_GEORGIAN 0x37
156#endif
157#ifndef LANG_GUARANI
158#define LANG_GUARANI 0x74
159#endif
160#ifndef LANG_GUJARATI
161#define LANG_GUJARATI 0x47
162#endif
163#ifndef LANG_HAUSA
164#define LANG_HAUSA 0x68
165#endif
166#ifndef LANG_HAWAIIAN
167#define LANG_HAWAIIAN 0x75
168#endif
169#ifndef LANG_HEBREW
170#define LANG_HEBREW 0x0d
171#endif
172#ifndef LANG_HINDI
173#define LANG_HINDI 0x39
174#endif
175#ifndef LANG_IBIBIO
176#define LANG_IBIBIO 0x69
177#endif
178#ifndef LANG_IGBO
179#define LANG_IGBO 0x70
180#endif
181#ifndef LANG_INDONESIAN
182#define LANG_INDONESIAN 0x21
183#endif
184#ifndef LANG_INUKTITUT
185#define LANG_INUKTITUT 0x5d
186#endif
187#ifndef LANG_KANNADA
188#define LANG_KANNADA 0x4b
189#endif
190#ifndef LANG_KANURI
191#define LANG_KANURI 0x71
192#endif
193#ifndef LANG_KASHMIRI
194#define LANG_KASHMIRI 0x60
195#endif
196#ifndef LANG_KAZAK
197#define LANG_KAZAK 0x3f
198#endif
199#ifndef LANG_KONKANI
200#define LANG_KONKANI 0x57
201#endif
202#ifndef LANG_KYRGYZ
203#define LANG_KYRGYZ 0x40
204#endif
205#ifndef LANG_LAO
206#define LANG_LAO 0x54
207#endif
208#ifndef LANG_LATIN
209#define LANG_LATIN 0x76
210#endif
211#ifndef LANG_LATVIAN
212#define LANG_LATVIAN 0x26
213#endif
214#ifndef LANG_LITHUANIAN
215#define LANG_LITHUANIAN 0x27
216#endif
217#ifndef LANG_MACEDONIAN
218#define LANG_MACEDONIAN 0x2f
219#endif
220#ifndef LANG_MALAY
221#define LANG_MALAY 0x3e
222#endif
223#ifndef LANG_MALAYALAM
224#define LANG_MALAYALAM 0x4c
225#endif
226#ifndef LANG_MALTESE
227#define LANG_MALTESE 0x3a
228#endif
229#ifndef LANG_MANIPURI
230#define LANG_MANIPURI 0x58
231#endif
232#ifndef LANG_MARATHI
233#define LANG_MARATHI 0x4e
234#endif
235#ifndef LANG_MONGOLIAN
236#define LANG_MONGOLIAN 0x50
237#endif
238#ifndef LANG_NEPALI
239#define LANG_NEPALI 0x61
240#endif
241#ifndef LANG_ORIYA
242#define LANG_ORIYA 0x48
243#endif
244#ifndef LANG_OROMO
245#define LANG_OROMO 0x72
246#endif
247#ifndef LANG_PAPIAMENTU
248#define LANG_PAPIAMENTU 0x79
249#endif
250#ifndef LANG_PASHTO
251#define LANG_PASHTO 0x63
252#endif
253#ifndef LANG_PUNJABI
254#define LANG_PUNJABI 0x46
255#endif
256#ifndef LANG_RHAETO_ROMANCE
257#define LANG_RHAETO_ROMANCE 0x17
258#endif
259#ifndef LANG_SAAMI
260#define LANG_SAAMI 0x3b
261#endif
262#ifndef LANG_SANSKRIT
263#define LANG_SANSKRIT 0x4f
264#endif
265#ifndef LANG_SERBIAN
266#define LANG_SERBIAN 0x1a
267#endif
268#ifndef LANG_SINDHI
269#define LANG_SINDHI 0x59
270#endif
271#ifndef LANG_SINHALESE
272#define LANG_SINHALESE 0x5b
273#endif
274#ifndef LANG_SLOVAK
275#define LANG_SLOVAK 0x1b
276#endif
277#ifndef LANG_SOMALI
278#define LANG_SOMALI 0x77
279#endif
280#ifndef LANG_SORBIAN
281#define LANG_SORBIAN 0x2e
282#endif
283#ifndef LANG_SUTU
284#define LANG_SUTU 0x30
285#endif
286#ifndef LANG_SWAHILI
287#define LANG_SWAHILI 0x41
288#endif
289#ifndef LANG_SYRIAC
290#define LANG_SYRIAC 0x5a
291#endif
292#ifndef LANG_TAGALOG
293#define LANG_TAGALOG 0x64
294#endif
295#ifndef LANG_TAJIK
296#define LANG_TAJIK 0x28
297#endif
298#ifndef LANG_TAMAZIGHT
299#define LANG_TAMAZIGHT 0x5f
300#endif
301#ifndef LANG_TAMIL
302#define LANG_TAMIL 0x49
303#endif
304#ifndef LANG_TATAR
305#define LANG_TATAR 0x44
306#endif
307#ifndef LANG_TELUGU
308#define LANG_TELUGU 0x4a
309#endif
310#ifndef LANG_THAI
311#define LANG_THAI 0x1e
312#endif
313#ifndef LANG_TIBETAN
314#define LANG_TIBETAN 0x51
315#endif
316#ifndef LANG_TIGRINYA
317#define LANG_TIGRINYA 0x73
318#endif
319#ifndef LANG_TSONGA
320#define LANG_TSONGA 0x31
321#endif
322#ifndef LANG_TSWANA
323#define LANG_TSWANA 0x32
324#endif
325#ifndef LANG_TURKMEN
326#define LANG_TURKMEN 0x42
327#endif
328#ifndef LANG_UKRAINIAN
329#define LANG_UKRAINIAN 0x22
330#endif
331#ifndef LANG_URDU
332#define LANG_URDU 0x20
333#endif
334#ifndef LANG_UZBEK
335#define LANG_UZBEK 0x43
336#endif
337#ifndef LANG_VENDA
338#define LANG_VENDA 0x33
339#endif
340#ifndef LANG_VIETNAMESE
341#define LANG_VIETNAMESE 0x2a
342#endif
343#ifndef LANG_WELSH
344#define LANG_WELSH 0x52
345#endif
346#ifndef LANG_XHOSA
347#define LANG_XHOSA 0x34
348#endif
349#ifndef LANG_YI
350#define LANG_YI 0x78
351#endif
352#ifndef LANG_YIDDISH
353#define LANG_YIDDISH 0x3d
354#endif
355#ifndef LANG_YORUBA
356#define LANG_YORUBA 0x6a
357#endif
358#ifndef LANG_ZULU
359#define LANG_ZULU 0x35
360#endif
361#ifndef SUBLANG_ARABIC_SAUDI_ARABIA
362#define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
363#endif
364#ifndef SUBLANG_ARABIC_IRAQ
365#define SUBLANG_ARABIC_IRAQ 0x02
366#endif
367#ifndef SUBLANG_ARABIC_EGYPT
368#define SUBLANG_ARABIC_EGYPT 0x03
369#endif
370#ifndef SUBLANG_ARABIC_LIBYA
371#define SUBLANG_ARABIC_LIBYA 0x04
372#endif
373#ifndef SUBLANG_ARABIC_ALGERIA
374#define SUBLANG_ARABIC_ALGERIA 0x05
375#endif
376#ifndef SUBLANG_ARABIC_MOROCCO
377#define SUBLANG_ARABIC_MOROCCO 0x06
378#endif
379#ifndef SUBLANG_ARABIC_TUNISIA
380#define SUBLANG_ARABIC_TUNISIA 0x07
381#endif
382#ifndef SUBLANG_ARABIC_OMAN
383#define SUBLANG_ARABIC_OMAN 0x08
384#endif
385#ifndef SUBLANG_ARABIC_YEMEN
386#define SUBLANG_ARABIC_YEMEN 0x09
387#endif
388#ifndef SUBLANG_ARABIC_SYRIA
389#define SUBLANG_ARABIC_SYRIA 0x0a
390#endif
391#ifndef SUBLANG_ARABIC_JORDAN
392#define SUBLANG_ARABIC_JORDAN 0x0b
393#endif
394#ifndef SUBLANG_ARABIC_LEBANON
395#define SUBLANG_ARABIC_LEBANON 0x0c
396#endif
397#ifndef SUBLANG_ARABIC_KUWAIT
398#define SUBLANG_ARABIC_KUWAIT 0x0d
399#endif
400#ifndef SUBLANG_ARABIC_UAE
401#define SUBLANG_ARABIC_UAE 0x0e
402#endif
403#ifndef SUBLANG_ARABIC_BAHRAIN
404#define SUBLANG_ARABIC_BAHRAIN 0x0f
405#endif
406#ifndef SUBLANG_ARABIC_QATAR
407#define SUBLANG_ARABIC_QATAR 0x10
408#endif
409#ifndef SUBLANG_AZERI_LATIN
410#define SUBLANG_AZERI_LATIN 0x01
411#endif
412#ifndef SUBLANG_AZERI_CYRILLIC
413#define SUBLANG_AZERI_CYRILLIC 0x02
414#endif
415#ifndef SUBLANG_BENGALI_INDIA
416#define SUBLANG_BENGALI_INDIA 0x00
417#endif
418#ifndef SUBLANG_BENGALI_BANGLADESH
419#define SUBLANG_BENGALI_BANGLADESH 0x01
420#endif
421#ifndef SUBLANG_CHINESE_MACAU
422#define SUBLANG_CHINESE_MACAU 0x05
423#endif
424#ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
425#define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
426#endif
427#ifndef SUBLANG_ENGLISH_JAMAICA
428#define SUBLANG_ENGLISH_JAMAICA 0x08
429#endif
430#ifndef SUBLANG_ENGLISH_CARIBBEAN
431#define SUBLANG_ENGLISH_CARIBBEAN 0x09
432#endif
433#ifndef SUBLANG_ENGLISH_BELIZE
434#define SUBLANG_ENGLISH_BELIZE 0x0a
435#endif
436#ifndef SUBLANG_ENGLISH_TRINIDAD
437#define SUBLANG_ENGLISH_TRINIDAD 0x0b
438#endif
439#ifndef SUBLANG_ENGLISH_ZIMBABWE
440#define SUBLANG_ENGLISH_ZIMBABWE 0x0c
441#endif
442#ifndef SUBLANG_ENGLISH_PHILIPPINES
443#define SUBLANG_ENGLISH_PHILIPPINES 0x0d
444#endif
445#ifndef SUBLANG_ENGLISH_INDONESIA
446#define SUBLANG_ENGLISH_INDONESIA 0x0e
447#endif
448#ifndef SUBLANG_ENGLISH_HONGKONG
449#define SUBLANG_ENGLISH_HONGKONG 0x0f
450#endif
451#ifndef SUBLANG_ENGLISH_INDIA
452#define SUBLANG_ENGLISH_INDIA 0x10
453#endif
454#ifndef SUBLANG_ENGLISH_MALAYSIA
455#define SUBLANG_ENGLISH_MALAYSIA 0x11
456#endif
457#ifndef SUBLANG_ENGLISH_SINGAPORE
458#define SUBLANG_ENGLISH_SINGAPORE 0x12
459#endif
460#ifndef SUBLANG_FRENCH_LUXEMBOURG
461#define SUBLANG_FRENCH_LUXEMBOURG 0x05
462#endif
463#ifndef SUBLANG_FRENCH_MONACO
464#define SUBLANG_FRENCH_MONACO 0x06
465#endif
466#ifndef SUBLANG_FRENCH_WESTINDIES
467#define SUBLANG_FRENCH_WESTINDIES 0x07
468#endif
469#ifndef SUBLANG_FRENCH_REUNION
470#define SUBLANG_FRENCH_REUNION 0x08
471#endif
472#ifndef SUBLANG_FRENCH_CONGO
473#define SUBLANG_FRENCH_CONGO 0x09
474#endif
475#ifndef SUBLANG_FRENCH_SENEGAL
476#define SUBLANG_FRENCH_SENEGAL 0x0a
477#endif
478#ifndef SUBLANG_FRENCH_CAMEROON
479#define SUBLANG_FRENCH_CAMEROON 0x0b
480#endif
481#ifndef SUBLANG_FRENCH_COTEDIVOIRE
482#define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
483#endif
484#ifndef SUBLANG_FRENCH_MALI
485#define SUBLANG_FRENCH_MALI 0x0d
486#endif
487#ifndef SUBLANG_FRENCH_MOROCCO
488#define SUBLANG_FRENCH_MOROCCO 0x0e
489#endif
490#ifndef SUBLANG_FRENCH_HAITI
491#define SUBLANG_FRENCH_HAITI 0x0f
492#endif
493#ifndef SUBLANG_GERMAN_LUXEMBOURG
494#define SUBLANG_GERMAN_LUXEMBOURG 0x04
495#endif
496#ifndef SUBLANG_GERMAN_LIECHTENSTEIN
497#define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
498#endif
499#ifndef SUBLANG_KASHMIRI_INDIA
500#define SUBLANG_KASHMIRI_INDIA 0x02
501#endif
502#ifndef SUBLANG_MALAY_MALAYSIA
503#define SUBLANG_MALAY_MALAYSIA 0x01
504#endif
505#ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
506#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
507#endif
508#ifndef SUBLANG_NEPALI_INDIA
509#define SUBLANG_NEPALI_INDIA 0x02
510#endif
511#ifndef SUBLANG_PUNJABI_INDIA
512#define SUBLANG_PUNJABI_INDIA 0x00
513#endif
514#ifndef SUBLANG_PUNJABI_PAKISTAN
515#define SUBLANG_PUNJABI_PAKISTAN 0x01
516#endif
517#ifndef SUBLANG_ROMANIAN_ROMANIA
518#define SUBLANG_ROMANIAN_ROMANIA 0x00
519#endif
520#ifndef SUBLANG_ROMANIAN_MOLDOVA
521#define SUBLANG_ROMANIAN_MOLDOVA 0x01
522#endif
523#ifndef SUBLANG_SERBIAN_LATIN
524#define SUBLANG_SERBIAN_LATIN 0x02
525#endif
526#ifndef SUBLANG_SERBIAN_CYRILLIC
527#define SUBLANG_SERBIAN_CYRILLIC 0x03
528#endif
529#ifndef SUBLANG_SINDHI_INDIA
530#define SUBLANG_SINDHI_INDIA 0x00
531#endif
532#ifndef SUBLANG_SINDHI_PAKISTAN
533#define SUBLANG_SINDHI_PAKISTAN 0x01
534#endif
535#ifndef SUBLANG_SPANISH_GUATEMALA
536#define SUBLANG_SPANISH_GUATEMALA 0x04
537#endif
538#ifndef SUBLANG_SPANISH_COSTA_RICA
539#define SUBLANG_SPANISH_COSTA_RICA 0x05
540#endif
541#ifndef SUBLANG_SPANISH_PANAMA
542#define SUBLANG_SPANISH_PANAMA 0x06
543#endif
544#ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
545#define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
546#endif
547#ifndef SUBLANG_SPANISH_VENEZUELA
548#define SUBLANG_SPANISH_VENEZUELA 0x08
549#endif
550#ifndef SUBLANG_SPANISH_COLOMBIA
551#define SUBLANG_SPANISH_COLOMBIA 0x09
552#endif
553#ifndef SUBLANG_SPANISH_PERU
554#define SUBLANG_SPANISH_PERU 0x0a
555#endif
556#ifndef SUBLANG_SPANISH_ARGENTINA
557#define SUBLANG_SPANISH_ARGENTINA 0x0b
558#endif
559#ifndef SUBLANG_SPANISH_ECUADOR
560#define SUBLANG_SPANISH_ECUADOR 0x0c
561#endif
562#ifndef SUBLANG_SPANISH_CHILE
563#define SUBLANG_SPANISH_CHILE 0x0d
564#endif
565#ifndef SUBLANG_SPANISH_URUGUAY
566#define SUBLANG_SPANISH_URUGUAY 0x0e
567#endif
568#ifndef SUBLANG_SPANISH_PARAGUAY
569#define SUBLANG_SPANISH_PARAGUAY 0x0f
570#endif
571#ifndef SUBLANG_SPANISH_BOLIVIA
572#define SUBLANG_SPANISH_BOLIVIA 0x10
573#endif
574#ifndef SUBLANG_SPANISH_EL_SALVADOR
575#define SUBLANG_SPANISH_EL_SALVADOR 0x11
576#endif
577#ifndef SUBLANG_SPANISH_HONDURAS
578#define SUBLANG_SPANISH_HONDURAS 0x12
579#endif
580#ifndef SUBLANG_SPANISH_NICARAGUA
581#define SUBLANG_SPANISH_NICARAGUA 0x13
582#endif
583#ifndef SUBLANG_SPANISH_PUERTO_RICO
584#define SUBLANG_SPANISH_PUERTO_RICO 0x14
585#endif
586#ifndef SUBLANG_SWEDISH_FINLAND
587#define SUBLANG_SWEDISH_FINLAND 0x02
588#endif
589#ifndef SUBLANG_TAMAZIGHT_ARABIC
590#define SUBLANG_TAMAZIGHT_ARABIC 0x01
591#endif
592#ifndef SUBLANG_TAMAZIGHT_LATIN
593#define SUBLANG_TAMAZIGHT_LATIN 0x02
594#endif
595#ifndef SUBLANG_TIGRINYA_ETHIOPIA
596#define SUBLANG_TIGRINYA_ETHIOPIA 0x00
597#endif
598#ifndef SUBLANG_TIGRINYA_ERITREA
599#define SUBLANG_TIGRINYA_ERITREA 0x01
600#endif
601#ifndef SUBLANG_URDU_PAKISTAN
602#define SUBLANG_URDU_PAKISTAN 0x01
603#endif
604#ifndef SUBLANG_URDU_INDIA
605#define SUBLANG_URDU_INDIA 0x02
606#endif
607#ifndef SUBLANG_UZBEK_LATIN
608#define SUBLANG_UZBEK_LATIN 0x01
609#endif
610#ifndef SUBLANG_UZBEK_CYRILLIC
611#define SUBLANG_UZBEK_CYRILLIC 0x02
612#endif
613
614gchar *
615g_win32_getlocale (void)
616{
617  LCID lcid;
618  LANGID langid;
619  gchar *ev;
620  gint primary, sub;
621  gchar *l = "C", *sl = NULL;
622  gchar bfr[20];
623
624  /* Let the user override the system settings through environment
625     variables, as on POSIX systems.  */
626  if (((ev = getenv ("LC_ALL")) != NULL && ev[0] != '\0')
627      || ((ev = getenv ("LC_MESSAGES")) != NULL && ev[0] != '\0')
628      || ((ev = getenv ("LANG")) != NULL && ev[0] != '\0'))
629    return g_strdup (ev);
630
631  /* Use native Win32 API locale ID.  */
632  lcid = GetThreadLocale ();
633
634  /* Strip off the sorting rules, keep only the language part.  */
635  langid = LANGIDFROMLCID (lcid);
636
637  /* Split into language and territory part.  */
638  primary = PRIMARYLANGID (langid);
639  sub = SUBLANGID (langid);
640  switch (primary)
641    {
642    case LANG_AFRIKAANS: l = "af"; sl = "ZA"; break;
643    case LANG_ALBANIAN: l = "sq"; sl = "AL"; break;
644    case LANG_ARABIC:
645      l = "ar";
646      switch (sub)
647        {
648        case SUBLANG_ARABIC_SAUDI_ARABIA: sl = "SA"; break;
649        case SUBLANG_ARABIC_IRAQ: sl = "IQ"; break;
650        case SUBLANG_ARABIC_EGYPT: sl = "EG"; break;
651        case SUBLANG_ARABIC_LIBYA: sl = "LY"; break;
652        case SUBLANG_ARABIC_ALGERIA: sl = "DZ"; break;
653        case SUBLANG_ARABIC_MOROCCO: sl = "MA"; break;
654        case SUBLANG_ARABIC_TUNISIA: sl = "TN"; break;
655        case SUBLANG_ARABIC_OMAN: sl = "OM"; break;
656        case SUBLANG_ARABIC_YEMEN: sl = "YE"; break;
657        case SUBLANG_ARABIC_SYRIA: sl = "SY"; break;
658        case SUBLANG_ARABIC_JORDAN: sl = "JO"; break;
659        case SUBLANG_ARABIC_LEBANON: sl = "LB"; break;
660        case SUBLANG_ARABIC_KUWAIT: sl = "KW"; break;
661        case SUBLANG_ARABIC_UAE: sl = "AE"; break;
662        case SUBLANG_ARABIC_BAHRAIN: sl = "BH"; break;
663        case SUBLANG_ARABIC_QATAR: sl = "QA"; break;
664        }
665      break;
666    case LANG_ARMENIAN: l = "hy"; sl = "AM"; break;
667    case LANG_ASSAMESE: l = "as"; sl = "IN"; break;
668    case LANG_AZERI:
669      l = "az";
670      switch (sub)
671        {
672        /* FIXME: Adjust this when Azerbaijani locales appear on Unix.  */
673        case SUBLANG_AZERI_LATIN: sl = "AZ@latin"; break;
674        case SUBLANG_AZERI_CYRILLIC: sl = "AZ@cyrillic"; break;
675        }
676      break;
677    case LANG_BASQUE:
678      l = "eu"; /* sl could be "ES" or "FR".  */
679      break;
680    case LANG_BELARUSIAN: l = "be"; sl = "BY"; break;
681    case LANG_BENGALI:
682      l = "bn";
683      switch (sub)
684        {
685        case SUBLANG_BENGALI_INDIA: sl = "IN"; break;
686        case SUBLANG_BENGALI_BANGLADESH: sl = "BD"; break;
687        }
688      break;
689    case LANG_BULGARIAN: l = "bg"; sl = "BG"; break;
690    case LANG_BURMESE: l = "my"; sl = "MM"; break;
691    case LANG_CAMBODIAN: l = "km"; sl = "KH"; break;
692    case LANG_CATALAN: l = "ca"; sl = "ES"; break;
693    case LANG_CHINESE:
694      l = "zh";
695      switch (sub)
696        {
697        case SUBLANG_CHINESE_TRADITIONAL: sl = "TW"; break;
698        case SUBLANG_CHINESE_SIMPLIFIED: sl = "CN"; break;
699        case SUBLANG_CHINESE_HONGKONG: sl = "HK"; break;
700        case SUBLANG_CHINESE_SINGAPORE: sl = "SG"; break;
701        case SUBLANG_CHINESE_MACAU: sl = "MO"; break;
702        }
703      break;
704    case LANG_CROATIAN:         /* LANG_CROATIAN == LANG_SERBIAN */
705      switch (sub)
706        {
707        /* FIXME: How to distinguish Croatian and Latin Serbian locales?  */
708        case SUBLANG_SERBIAN_LATIN: l = "sr"; sl = "@Latn"; break;
709        case SUBLANG_SERBIAN_CYRILLIC: l = "sr"; break;
710        default: l = "hr"; sl = "HR";
711        }
712      break;
713    case LANG_CZECH: l = "cs"; sl = "CZ"; break;
714    case LANG_DANISH: l = "da"; sl = "DK"; break;
715    case LANG_DIVEHI: l = "div"; sl = "MV"; break;
716    case LANG_DUTCH:
717      l = "nl";
718      switch (sub)
719        {
720        case SUBLANG_DUTCH: sl = "NL"; break;
721        case SUBLANG_DUTCH_BELGIAN: sl = "BE"; break;
722        }
723      break;
724    case LANG_ENGLISH:
725      l = "en";
726      switch (sub)
727        {
728        case SUBLANG_ENGLISH_US: sl = "US"; break;
729        case SUBLANG_ENGLISH_UK: sl = "GB"; break;
730        case SUBLANG_ENGLISH_AUS: sl = "AU"; break;
731        case SUBLANG_ENGLISH_CAN: sl = "CA"; break;
732        case SUBLANG_ENGLISH_NZ: sl = "NZ"; break;
733        case SUBLANG_ENGLISH_EIRE: sl = "IE"; break;
734        case SUBLANG_ENGLISH_SOUTH_AFRICA: sl = "ZA"; break;
735        case SUBLANG_ENGLISH_JAMAICA: sl = "JM"; break;
736        case SUBLANG_ENGLISH_CARIBBEAN: sl = "GD"; break; /* Grenada? */
737        case SUBLANG_ENGLISH_BELIZE: sl = "BZ"; break;
738        case SUBLANG_ENGLISH_TRINIDAD: sl = "TT"; break;
739        case SUBLANG_ENGLISH_ZIMBABWE: sl = "ZW"; break;
740        case SUBLANG_ENGLISH_PHILIPPINES: sl = "PH"; break;
741        case SUBLANG_ENGLISH_INDONESIA: sl = "ID"; break;
742        case SUBLANG_ENGLISH_HONGKONG: sl = "HK"; break;
743        case SUBLANG_ENGLISH_INDIA: sl = "IN"; break;
744        case SUBLANG_ENGLISH_MALAYSIA: sl = "MY"; break;
745        case SUBLANG_ENGLISH_SINGAPORE: sl = "SG"; break;
746        }
747      break;
748    case LANG_ESTONIAN: l = "et"; sl = "EE"; break;
749    case LANG_FAEROESE: l = "fo"; sl = "FO"; break;
750    case LANG_FARSI: l = "fa"; sl = "IR"; break;
751    case LANG_FINNISH: l = "fi"; sl = "FI"; break;
752    case LANG_FRENCH:
753      l = "fr";
754      switch (sub)
755        {
756        case SUBLANG_FRENCH: sl = "FR"; break;
757        case SUBLANG_FRENCH_BELGIAN: sl = "BE"; break;
758        case SUBLANG_FRENCH_CANADIAN: sl = "CA"; break;
759        case SUBLANG_FRENCH_SWISS: sl = "CH"; break;
760        case SUBLANG_FRENCH_LUXEMBOURG: sl = "LU"; break;
761        case SUBLANG_FRENCH_MONACO: sl = "MC"; break;
762        case SUBLANG_FRENCH_WESTINDIES: break;
763        case SUBLANG_FRENCH_REUNION: sl = "RE"; break;
764        case SUBLANG_FRENCH_CONGO: sl = "CG"; break;
765        case SUBLANG_FRENCH_SENEGAL: sl = "SN"; break;
766        case SUBLANG_FRENCH_CAMEROON: sl = "CM"; break;
767        case SUBLANG_FRENCH_COTEDIVOIRE: sl = "CI"; break;
768        case SUBLANG_FRENCH_MALI: sl = "ML"; break;
769        case SUBLANG_FRENCH_MOROCCO: sl = "MA"; break;
770        case SUBLANG_FRENCH_HAITI: sl = "HT"; break;
771        }
772      break;
773    case LANG_FRISIAN: l = "fy"; sl ="NL"; break;
774    case LANG_FULFULDE: l = "ful"; sl = "NG"; break;
775    case LANG_GAELIC:
776      switch (sub)
777        {
778        case 0x01: /* SCOTTISH */ l = "gd"; sl = "GB"; break;
779        case 0x02: /* IRISH */ l = "ga"; sl = "IE"; break;
780        }
781      break;
782    case LANG_GALICIAN: l = "gl"; sl = "ES"; break;
783    case LANG_GEORGIAN: l = "ka"; sl = "GE"; break;
784    case LANG_GERMAN:
785      l = "de";
786      switch (sub)
787        {
788        case SUBLANG_GERMAN: sl = "DE"; break;
789        case SUBLANG_GERMAN_SWISS: sl = "CH"; break;
790        case SUBLANG_GERMAN_AUSTRIAN: sl = "AT"; break;
791        case SUBLANG_GERMAN_LUXEMBOURG: sl = "LU"; break;
792        case SUBLANG_GERMAN_LIECHTENSTEIN: sl = "LI"; break;
793        }
794      break;
795    case LANG_GREEK: l = "el"; sl = "GR"; break;
796    case LANG_GUARANI: l = "gn"; sl = "PY"; break;
797    case LANG_GUJARATI: l = "gu"; sl = "IN"; break;
798    case LANG_HAUSA: l = "ha"; sl = "NG"; break;
799    case LANG_HAWAIIAN:
800      /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
801       * or Hawaii Creole English ("cpe_US", 600000 speakers)?
802       */
803      l = "cpe";
804      sl = "US";
805      break;
806    case LANG_HEBREW: l = "he"; sl = "IL"; break;
807    case LANG_HINDI: l = "hi"; sl = "IN"; break;
808    case LANG_HUNGARIAN: l = "hu"; sl = "HU"; break;
809    case LANG_IBIBIO: l = "nic"; sl = "NG"; break;
810    case LANG_ICELANDIC: l = "is"; sl = "IS"; break;
811    case LANG_IGBO: l = "ibo"; sl = "NG"; break;
812    case LANG_INDONESIAN: l = "id"; sl = "ID"; break;
813    case LANG_INUKTITUT: l = "iu"; sl = "CA"; break;
814    case LANG_ITALIAN:
815      l = "it";
816      switch (sub)
817        {
818        case SUBLANG_ITALIAN: sl = "IT"; break;
819        case SUBLANG_ITALIAN_SWISS: sl = "CH"; break;
820        }
821      break;
822    case LANG_JAPANESE: l = "ja"; sl = "JP"; break;
823    case LANG_KANNADA: l = "kn"; sl = "IN"; break;
824    case LANG_KANURI: l = "kau"; sl = "NG"; break;
825    case LANG_KASHMIRI:
826      l = "ks";
827      switch (sub)
828        {
829        case SUBLANG_DEFAULT: sl = "PK"; break;
830        case SUBLANG_KASHMIRI_INDIA: sl = "IN"; break;
831        }
832      break;
833    case LANG_KAZAK: l = "kk"; sl = "KZ"; break;
834    case LANG_KONKANI:
835      /* FIXME: Adjust this when such locales appear on Unix.  */
836      l = "kok";
837      sl = "IN";
838      break;
839    case LANG_KOREAN: l = "ko"; sl = "KR"; break;
840    case LANG_KYRGYZ: l = "ky"; sl = "KG"; break;
841    case LANG_LAO: l = "lo"; sl = "LA"; break;
842    case LANG_LATIN: l = "la"; sl = "VA"; break;
843    case LANG_LATVIAN: l = "lv"; sl = "LV"; break;
844    case LANG_LITHUANIAN: l = "lt"; sl = "LT"; break;
845    case LANG_MACEDONIAN: l = "mk"; sl = "MK"; break;
846    case LANG_MALAY:
847      l = "ms";
848      switch (sub)
849        {
850        case SUBLANG_MALAY_MALAYSIA: sl = "MY"; break;
851        case SUBLANG_MALAY_BRUNEI_DARUSSALAM: sl = "BN"; break;
852        }
853      break;
854    case LANG_MALAYALAM: l = "ml"; sl = "IN"; break;
855    case LANG_MANIPURI:
856      /* FIXME: Adjust this when such locales appear on Unix.  */
857      l = "mni";
858      sl = "IN";
859      break;
860    case LANG_MARATHI: l = "mr"; sl = "IN"; break;
861    case LANG_MONGOLIAN:
862      /* Ambiguous: could be "mn_CN" or "mn_MN".  */
863      l = "mn";
864      break;
865    case LANG_NEPALI:
866      l = "ne";
867      switch (sub)
868        {
869        case SUBLANG_DEFAULT: sl = "NP"; break;
870        case SUBLANG_NEPALI_INDIA: sl = "IN"; break;
871        }
872      break;
873    case LANG_NORWEGIAN:
874      l = "no";
875      switch (sub)
876        {
877        case SUBLANG_NORWEGIAN_BOKMAL: sl = "NO"; break;
878        case SUBLANG_NORWEGIAN_NYNORSK: l = "nn"; sl = "NO"; break;
879        }
880      break;
881    case LANG_ORIYA: l = "or"; sl = "IN"; break;
882    case LANG_OROMO: l = "om"; sl = "ET"; break;
883    case LANG_PAPIAMENTU: l = "pap"; sl = "AN"; break;
884    case LANG_PASHTO:
885      /* Ambiguous: could be "ps_PK" or "ps_AF".  */
886      l = "ps";
887      break;
888    case LANG_POLISH: l = "pl"; sl = "PL"; break;
889    case LANG_PORTUGUESE:
890      l = "pt";
891      switch (sub)
892        {
893        case SUBLANG_PORTUGUESE: sl = "PT"; break;
894        case SUBLANG_PORTUGUESE_BRAZILIAN: sl = "BR"; break;
895        }
896      break;
897    case LANG_PUNJABI:
898      l = "pa";
899      switch (sub)
900        {
901        case SUBLANG_PUNJABI_INDIA: sl = "IN"; break; /* Gurmukhi script */
902        case SUBLANG_PUNJABI_PAKISTAN: sl = "PK"; break; /* Arabic script */
903        }
904      break;
905    case LANG_RHAETO_ROMANCE: l = "rm"; sl = "CH"; break;
906    case LANG_ROMANIAN:
907      l = "ro";
908      switch (sub)
909        {
910        case SUBLANG_ROMANIAN_ROMANIA: sl = "RO"; break;
911        case SUBLANG_ROMANIAN_MOLDOVA: sl = "MD"; break;
912        }
913      break;
914    case LANG_RUSSIAN:
915      l = "ru";/* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
916      break;
917    case LANG_SAAMI: /* actually Northern Sami */ l = "se"; sl = "NO"; break;
918    case LANG_SANSKRIT: l = "sa"; sl = "IN"; break;
919    case LANG_SINDHI: l = "sd";
920      switch (sub)
921        {
922        case SUBLANG_SINDHI_INDIA: sl = "IN"; break;
923        case SUBLANG_SINDHI_PAKISTAN: sl = "PK"; break;
924        }
925      break;
926    case LANG_SINHALESE: l = "si"; sl = "LK"; break;
927    case LANG_SLOVAK: l = "sk"; sl = "SK"; break;
928    case LANG_SLOVENIAN: l = "sl"; sl = "SI"; break;
929    case LANG_SOMALI: l = "so"; sl = "SO"; break;
930    case LANG_SORBIAN:
931      /* FIXME: Adjust this when such locales appear on Unix.  */
932      l = "wen";
933      sl = "DE";
934      break;
935    case LANG_SPANISH:
936      l = "es";
937      switch (sub)
938        {
939        case SUBLANG_SPANISH: sl = "ES"; break;
940        case SUBLANG_SPANISH_MEXICAN: sl = "MX"; break;
941        case SUBLANG_SPANISH_MODERN:
942          sl = "ES@modern"; break;      /* not seen on Unix */
943        case SUBLANG_SPANISH_GUATEMALA: sl = "GT"; break;
944        case SUBLANG_SPANISH_COSTA_RICA: sl = "CR"; break;
945        case SUBLANG_SPANISH_PANAMA: sl = "PA"; break;
946        case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: sl = "DO"; break;
947        case SUBLANG_SPANISH_VENEZUELA: sl = "VE"; break;
948        case SUBLANG_SPANISH_COLOMBIA: sl = "CO"; break;
949        case SUBLANG_SPANISH_PERU: sl = "PE"; break;
950        case SUBLANG_SPANISH_ARGENTINA: sl = "AR"; break;
951        case SUBLANG_SPANISH_ECUADOR: sl = "EC"; break;
952        case SUBLANG_SPANISH_CHILE: sl = "CL"; break;
953        case SUBLANG_SPANISH_URUGUAY: sl = "UY"; break;
954        case SUBLANG_SPANISH_PARAGUAY: sl = "PY"; break;
955        case SUBLANG_SPANISH_BOLIVIA: sl = "BO"; break;
956        case SUBLANG_SPANISH_EL_SALVADOR: sl = "SV"; break;
957        case SUBLANG_SPANISH_HONDURAS: sl = "HN"; break;
958        case SUBLANG_SPANISH_NICARAGUA: sl = "NI"; break;
959        case SUBLANG_SPANISH_PUERTO_RICO: sl = "PR"; break;
960        }
961      break;
962    case LANG_SUTU: l = "bnt"; sl = "TZ"; break; /* or "st_LS" or "nso_ZA"? */
963    case LANG_SWAHILI: l = "sw"; sl = "KE"; break;
964    case LANG_SWEDISH:
965      l = "sv";
966      switch (sub)
967        {
968        case SUBLANG_DEFAULT: sl = "SE"; break;
969        case SUBLANG_SWEDISH_FINLAND: sl = "FI"; break;
970        }
971      break;
972    case LANG_SYRIAC: l = "syr"; sl = "TR"; break; /* An extinct language. */
973    case LANG_TAGALOG: l = "tl"; sl = "PH"; break;
974    case LANG_TAJIK: l = "tg"; sl = "TJ"; break;
975    case LANG_TAMIL:
976      l = "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
977      break;
978    case LANG_TATAR: l = "tt"; sl = "RU"; break;
979    case LANG_TELUGU: l = "te"; sl = "IN"; break;
980    case LANG_THAI: l = "th"; sl = "TH"; break;
981    case LANG_TIBETAN: l = "bo"; sl = "CN"; break;
982    case LANG_TIGRINYA:
983      l = "ti";
984      switch (sub)
985        {
986        case SUBLANG_TIGRINYA_ETHIOPIA: sl = "ET"; break;
987        case SUBLANG_TIGRINYA_ERITREA: sl = "ER"; break;
988        }
989      break;
990    case LANG_TSONGA: l = "ts"; sl = "ZA"; break;
991    case LANG_TSWANA: l = "tn"; sl = "BW"; break;
992    case LANG_TURKISH: l = "tr"; sl = "TR"; break;
993    case LANG_TURKMEN: l = "tk"; sl = "TM"; break;
994    case LANG_UKRAINIAN: l = "uk"; sl = "UA"; break;
995    case LANG_URDU:
996      l = "ur";
997      switch (sub)
998        {
999        case SUBLANG_URDU_PAKISTAN: sl = "PK"; break;
1000        case SUBLANG_URDU_INDIA: sl = "IN"; break;
1001        }
1002      break;
1003    case LANG_UZBEK:
1004      l = "uz";
1005      switch (sub)
1006        {
1007        case SUBLANG_UZBEK_LATIN: sl = "UZ"; break;
1008        case SUBLANG_UZBEK_CYRILLIC: sl = "UZ@cyrillic"; break;
1009        }
1010      break;
1011    case LANG_VENDA:
1012      /* FIXME: It's not clear whether Venda has the ISO 639-2 two-letter code
1013         "ve" or not.
1014         http://www.loc.gov/standards/iso639-2/englangn.html has it, but
1015         http://lcweb.loc.gov/standards/iso639-2/codechanges.html doesn't,  */
1016      l = "ven"; /* or "ve"? */
1017      sl = "ZA";
1018      break;
1019    case LANG_VIETNAMESE: l = "vi"; sl = "VN"; break;
1020    case LANG_WELSH: l = "cy"; sl = "GB"; break;
1021    case LANG_XHOSA: l = "xh"; sl = "ZA"; break;
1022    case LANG_YI: l = "sit"; sl = "CN"; break;
1023    case LANG_YIDDISH: l = "yi"; sl = "IL"; break;
1024    case LANG_YORUBA: l = "yo"; sl = "NG"; break;
1025    case LANG_ZULU: l = "zu"; sl = "ZA"; break;
1026    }
1027  strcpy (bfr, l);
1028  if (sl != NULL)
1029    {
1030      if (sl[0] != '@')
1031        strcat (bfr, "_");
1032      strcat (bfr, sl);
1033    }
1034
1035  return g_strdup (bfr);
1036}
1037
1038/**
1039 * g_win32_error_message:
1040 * @error: error code.
1041 *
1042 * Translate a Win32 error code (as returned by GetLastError()) into
1043 * the corresponding message. The message is either language neutral,
1044 * or in the thread's language, or the user's language, the system's
1045 * language, or US English (see docs for FormatMessage()). The
1046 * returned string is in UTF-8. It should be deallocated with
1047 * g_free().
1048 *
1049 * Returns: newly-allocated error message
1050 **/
1051gchar *
1052g_win32_error_message (gint error)
1053{
1054  gchar *msg = NULL;
1055  gchar *retval;
1056  int nbytes;
1057
1058  FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
1059                 |FORMAT_MESSAGE_IGNORE_INSERTS
1060                 |FORMAT_MESSAGE_FROM_SYSTEM,
1061                 NULL, error, 0,
1062                 (LPTSTR) &msg, 0, NULL);
1063  if (msg != NULL)
1064    {
1065      nbytes = strlen (msg);
1066
1067      if (nbytes > 2 && msg[nbytes-1] == '\n' && msg[nbytes-2] == '\r')
1068        msg[nbytes-2] = '\0';
1069 
1070      retval = g_locale_to_utf8 (msg, -1, NULL, NULL, NULL);
1071
1072      LocalFree (msg);
1073    }
1074  else
1075    retval = g_strdup ("");
1076
1077  return retval;
1078}
1079
1080static gchar *
1081get_package_directory_from_module (gchar *module_name)
1082{
1083  static GHashTable *module_dirs = NULL;
1084  G_LOCK_DEFINE_STATIC (module_dirs);
1085  HMODULE hmodule = NULL;
1086  gchar *fn;
1087  gchar *p;
1088  gchar *result;
1089
1090  G_LOCK (module_dirs);
1091
1092  if (module_dirs == NULL)
1093    module_dirs = g_hash_table_new (g_str_hash, g_str_equal);
1094 
1095  result = g_hash_table_lookup (module_dirs, module_name ? module_name : "");
1096     
1097  if (result)
1098    {
1099      G_UNLOCK (module_dirs);
1100      return g_strdup (result);
1101    }
1102
1103  if (module_name)
1104    {
1105      hmodule = GetModuleHandle (module_name);
1106      if (!hmodule)
1107        return NULL;
1108    }
1109
1110  fn = g_malloc (MAX_PATH);
1111  if (!GetModuleFileName (hmodule, fn, MAX_PATH))
1112    {
1113      G_UNLOCK (module_dirs);
1114      g_free (fn);
1115      return NULL;
1116    }
1117
1118  if ((p = strrchr (fn, G_DIR_SEPARATOR)) != NULL)
1119    *p = '\0';
1120
1121  p = strrchr (fn, G_DIR_SEPARATOR);
1122  if (p && (g_ascii_strcasecmp (p + 1, "bin") == 0 ||
1123            g_ascii_strcasecmp (p + 1, "lib") == 0))
1124    *p = '\0';
1125
1126#ifdef G_WITH_CYGWIN
1127  /* In Cygwin we need to have POSIX paths */
1128  {
1129    gchar tmp[MAX_PATH];
1130
1131    cygwin_conv_to_posix_path(fn, tmp);
1132    g_free(fn);
1133    fn = g_strdup(tmp);
1134  }
1135#endif
1136
1137  g_hash_table_insert (module_dirs, module_name ? module_name : "", fn);
1138
1139  G_UNLOCK (module_dirs);
1140
1141  return g_strdup (fn);
1142}
1143
1144/**
1145 * g_win32_get_package_installation_directory:
1146 * @package: An identifier for a software package, or %NULL
1147 * @dll_name: The name of a DLL that a package provides, or %NULL.
1148 *
1149 * Try to determine the installation directory for a software package.
1150 * Typically used by GNU software packages.
1151 *
1152 * @package should be a short identifier for the package. Typically it
1153 * is the same identifier as used for
1154 * <literal>GETTEXT_PACKAGE</literal> in software configured according
1155 * to GNU standards. The function first looks in the Windows Registry
1156 * for the value <literal>&num;InstallationDirectory</literal> in the key
1157 * <literal>&num;HKLM\Software\@package</literal>, and if that value
1158 * exists and is a string, returns that.
1159 *
1160 * If @package is %NULL, or the above value isn't found in the
1161 * Registry, but @dll_name is non-%NULL, it should name a DLL loaded
1162 * into the current process. Typically that would be the name of the
1163 * DLL calling this function, looking for its installation
1164 * directory. The function then asks Windows what directory that DLL
1165 * was loaded from. If that directory's last component is "bin" or
1166 * "lib", the parent directory is returned, otherwise the directory
1167 * itself. If that DLL isn't loaded, the function proceeds as if
1168 * @dll_name was %NULL.
1169 *
1170 * If both @package and @dll_name are %NULL, the directory from where
1171 * the main executable of the process was loaded is uses instead in
1172 * the same way as above.
1173 *
1174 * Returns: a string containing the installation directory for @package.
1175 * The return value should be freed with g_free() when not needed any longer.
1176 **/
1177
1178gchar *
1179g_win32_get_package_installation_directory (gchar *package,
1180                                            gchar *dll_name)
1181{
1182  static GHashTable *package_dirs = NULL;
1183  G_LOCK_DEFINE_STATIC (package_dirs);
1184  gchar *result = NULL;
1185  gchar *key;
1186  HKEY reg_key = NULL;
1187  DWORD type;
1188  DWORD nbytes;
1189
1190  if (package != NULL)
1191    {
1192      G_LOCK (package_dirs);
1193     
1194      if (package_dirs == NULL)
1195        package_dirs = g_hash_table_new (g_str_hash, g_str_equal);
1196     
1197      result = g_hash_table_lookup (package_dirs, package);
1198     
1199      if (result && result[0])
1200        {
1201          G_UNLOCK (package_dirs);
1202          return g_strdup (result);
1203        }
1204     
1205      key = g_strconcat ("Software\\", package, NULL);
1206     
1207      nbytes = 0;
1208      if ((RegOpenKeyEx (HKEY_CURRENT_USER, key, 0,
1209                         KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS
1210           && RegQueryValueEx (reg_key, "InstallationDirectory", 0,
1211                               &type, NULL, &nbytes) == ERROR_SUCCESS)
1212          ||
1213          ((RegOpenKeyEx (HKEY_LOCAL_MACHINE, key, 0,
1214                         KEY_QUERY_VALUE, &reg_key) == ERROR_SUCCESS
1215           && RegQueryValueEx (reg_key, "InstallationDirectory", 0,
1216                               &type, NULL, &nbytes) == ERROR_SUCCESS)
1217           && type == REG_SZ))
1218        {
1219          result = g_malloc (nbytes + 1);
1220          RegQueryValueEx (reg_key, "InstallationDirectory", 0,
1221                           &type, result, &nbytes);
1222          result[nbytes] = '\0';
1223        }
1224
1225      if (reg_key != NULL)
1226        RegCloseKey (reg_key);
1227     
1228      g_free (key);
1229
1230      if (result)
1231        {
1232          g_hash_table_insert (package_dirs, package, result);
1233          G_UNLOCK (package_dirs);
1234          return g_strdup (result);
1235        }
1236      G_UNLOCK (package_dirs);
1237    }
1238
1239  if (dll_name != NULL)
1240    result = get_package_directory_from_module (dll_name);
1241
1242  if (result == NULL)
1243    result = get_package_directory_from_module (NULL);
1244
1245  return result;
1246}
1247
1248/**
1249 * g_win32_get_package_installation_subdirectory:
1250 * @package: An identifier for a software package, or %NULL.
1251 * @dll_name: The name of a DLL that a package provides, or %NULL.
1252 * @subdir: A subdirectory of the package installation directory.
1253 *
1254 * Returns a newly-allocated string containing the path of the
1255 * subdirectory @subdir in the return value from calling
1256 * g_win32_get_package_installation_directory() with the @package and
1257 * @dll_name parameters.
1258 *
1259 * Returns: a string containing the complete path to @subdir inside the
1260 * installation directory of @package. The return value should be freed with
1261 * g_free() when no longer needed.
1262 **/
1263
1264gchar *
1265g_win32_get_package_installation_subdirectory (gchar *package,
1266                                               gchar *dll_name,
1267                                               gchar *subdir)
1268{
1269  gchar *prefix;
1270  gchar *dirname;
1271
1272  prefix = g_win32_get_package_installation_directory (package, dll_name);
1273
1274  dirname = g_build_filename (prefix, subdir, NULL);
1275  g_free (prefix);
1276
1277  return dirname;
1278}
Note: See TracBrowser for help on using the repository browser.